diff --git a/llvm/test/tools/llvm-objcopy/ELF/execute-permissions.test b/llvm/test/tools/llvm-objcopy/ELF/execute-permissions.test
new file mode 100644
--- /dev/null
+++ b/llvm/test/tools/llvm-objcopy/ELF/execute-permissions.test
@@ -0,0 +1,25 @@
+# UNSUPPORTED: windows
+# REQUIRES: shell
+
+# RUN: umask 0
+# RUN: yaml2obj %s -o %t
+# RUN: llvm-objcopy %t %t1
+# RUN: test -x %t1
+
+# RUN: chmod 0666 %t
+# RUN: llvm-objcopy %t %t1
+# RUN: test -x %t1
+
+# RUN: llvm-objcopy %p/Inputs/alloc-symtab.o %t1
+# RUN: test ! -x %t1
+
+# RUN: chmod 0777 %t1
+# RUN: llvm-objcopy %t1 %t1
+# RUN: test ! -x %t1
+
+!ELF
+FileHeader:
+  Class:           ELFCLASS64
+  Data:            ELFDATA2LSB
+  Type:            ET_EXEC
+  Machine:         EM_X86_64
diff --git a/llvm/test/tools/llvm-objcopy/ELF/respect-umask.test b/llvm/test/tools/llvm-objcopy/ELF/respect-umask.test
new file mode 100644
--- /dev/null
+++ b/llvm/test/tools/llvm-objcopy/ELF/respect-umask.test
@@ -0,0 +1,28 @@
+# UNSUPPORTED: windows
+
+# RUN: touch test 
+# RUN: chmod 0777 test
+# RUN: ls -l test | cut -f 1 -d ' ' > %t.0777
+# RUN: chmod 0666 test
+# RUN: ls -l test | cut -f 1 -d ' ' > %t.0666
+# RUN: chmod 0640 test
+# RUN: ls -l test | cut -f 1 -d ' ' > %t.0640
+# RUN: chmod 0750 test
+# RUN: ls -l test | cut -f 1 -d ' ' > %t.0750
+# RUN: rm test
+
+# RUN: umask 0
+# RUN: llvm-objcopy %p/Inputs/alloc-symtab.o %t
+# RUN: ls -l %t | cut -f 1 -d ' ' > %t.perm
+# RUN: cmp %t.0666 %t.perm
+# RUN: llvm-objcopy %p/Inputs/dynrel.elf %t
+# RUN: ls -l %t | cut -f 1 -d ' ' > %t.perm
+# RUN: cmp %t.0777 %t.perm
+
+# RUN: umask 027
+# RUN: llvm-objcopy %p/Inputs/alloc-symtab.o %t
+# RUN: ls -l %t | cut -f 1 -d ' ' > %t.perm
+# RUN: cmp %t.0640 %t.perm
+# RUN: llvm-objcopy %p/Inputs/dynrel.elf %t
+# RUN: ls -l %t | cut -f 1 -d ' ' > %t.perm
+# RUN: cmp %t.0750 %t.perm
diff --git a/llvm/tools/llvm-objcopy/Buffer.h b/llvm/tools/llvm-objcopy/Buffer.h
--- a/llvm/tools/llvm-objcopy/Buffer.h
+++ b/llvm/tools/llvm-objcopy/Buffer.h
@@ -37,6 +37,7 @@
 
 class FileBuffer : public Buffer {
   std::unique_ptr<FileOutputBuffer> Buf;
+  unsigned Flags;
   // Indicates that allocate(0) was called, and commit() should create or
   // truncate a file instead of using a FileOutputBuffer.
   bool EmptyFile = false;
@@ -46,7 +47,8 @@
   uint8_t *getBufferStart() override;
   Error commit() override;
 
-  explicit FileBuffer(StringRef FileName) : Buffer(FileName) {}
+  explicit FileBuffer(StringRef FileName, unsigned Flags = 0)
+      : Buffer(FileName), Flags(Flags) {}
 };
 
 class MemBuffer : public Buffer {
diff --git a/llvm/tools/llvm-objcopy/Buffer.cpp b/llvm/tools/llvm-objcopy/Buffer.cpp
--- a/llvm/tools/llvm-objcopy/Buffer.cpp
+++ b/llvm/tools/llvm-objcopy/Buffer.cpp
@@ -36,7 +36,7 @@
   }
 
   Expected<std::unique_ptr<FileOutputBuffer>> BufferOrErr =
-      FileOutputBuffer::create(getName(), Size, FileOutputBuffer::F_executable);
+      FileOutputBuffer::create(getName(), Size, Flags);
   // FileOutputBuffer::create() returns an Error that is just a wrapper around
   // std::error_code. Wrap it in FileError to include the actual filename.
   if (!BufferOrErr)
diff --git a/llvm/tools/llvm-objcopy/llvm-objcopy.cpp b/llvm/tools/llvm-objcopy/llvm-objcopy.cpp
--- a/llvm/tools/llvm-objcopy/llvm-objcopy.cpp
+++ b/llvm/tools/llvm-objcopy/llvm-objcopy.cpp
@@ -149,6 +149,17 @@
                              "Unsupported object file format");
 }
 
+static bool isExecutableObject(object::Binary &Binary) {
+  if (auto *ELFObj = dyn_cast<object::ELFObjectFileBase>(&Binary))
+    return ELFObj->getEType() & ELF::ET_EXEC;
+  else if (auto *COFFObj = dyn_cast<object::COFFObjectFile>(&Binary))
+    return COFFObj->getCharacteristics() & COFF::IMAGE_FILE_EXECUTABLE_IMAGE;
+  else if (auto *MachOObj = dyn_cast<object::MachOObjectFile>(&Binary))
+    return MachOObj->getHeader().filetype == MachO::MH_EXECUTE;
+
+  return false;
+}
+
 static Error executeObjcopyOnArchive(const CopyConfig &Config,
                                      const Archive &Ar) {
   std::vector<NewArchiveMember> NewArchiveMembers;
@@ -164,7 +175,8 @@
                              ChildOrErr.takeError());
 
     MemBuffer MB(ChildNameOrErr.get());
-    if (Error E = executeObjcopyOnBinary(Config, *ChildOrErr->get(), MB))
+    object::Binary &Binary = *ChildOrErr->get();
+    if (Error E = executeObjcopyOnBinary(Config, Binary, MB))
       return E;
 
     Expected<NewArchiveMember> Member =
@@ -173,6 +185,7 @@
       return createFileError(Ar.getFileName(), Member.takeError());
     Member->Buf = MB.releaseMemoryBuffer();
     Member->MemberName = Member->Buf->getBufferIdentifier();
+    Member->Perms = isExecutableObject(Binary) ? 0777 : 0666;
     NewArchiveMembers.push_back(std::move(*Member));
   }
   if (Err)
@@ -227,9 +240,11 @@
       if (Error E = executeObjcopyOnArchive(Config, *Ar))
         return E;
     } else {
-      FileBuffer FB(Config.OutputFilename);
-      if (Error E = executeObjcopyOnBinary(Config,
-                                           *BinaryOrErr.get().getBinary(), FB))
+      object::Binary &Binary = *BinaryOrErr.get().getBinary();
+      FileBuffer FB(Config.OutputFilename, isExecutableObject(Binary)
+                                               ? FileOutputBuffer::F_executable
+                                               : 0);
+      if (Error E = executeObjcopyOnBinary(Config, Binary, FB))
         return E;
     }
   }