[llvm] a6e1b3c - [ObjectYAML][MachO] Add LC_FUNCTION_STARTS support

Keith Smiley via llvm-commits llvm-commits at lists.llvm.org
Sun Feb 13 09:27:55 PST 2022


Author: Keith Smiley
Date: 2022-02-13T09:24:47-08:00
New Revision: a6e1b3c5c223e4868ab77d6d66b62f136b12febc

URL: https://github.com/llvm/llvm-project/commit/a6e1b3c5c223e4868ab77d6d66b62f136b12febc
DIFF: https://github.com/llvm/llvm-project/commit/a6e1b3c5c223e4868ab77d6d66b62f136b12febc.diff

LOG: [ObjectYAML][MachO] Add LC_FUNCTION_STARTS support

This adds support for encoding and decoding the LC_FUNCTION_STARTS load
command payload.

Differential Revision: https://reviews.llvm.org/D119205

Added: 
    llvm/test/ObjectYAML/MachO/function_starts.yaml

Modified: 
    llvm/include/llvm/Object/MachO.h
    llvm/include/llvm/ObjectYAML/MachOYAML.h
    llvm/lib/Object/MachOObjectFile.cpp
    llvm/lib/ObjectYAML/MachOEmitter.cpp
    llvm/lib/ObjectYAML/MachOYAML.cpp
    llvm/tools/obj2yaml/macho2yaml.cpp

Removed: 
    


################################################################################
diff  --git a/llvm/include/llvm/Object/MachO.h b/llvm/include/llvm/Object/MachO.h
index 49a0706b84be..840faa700428 100644
--- a/llvm/include/llvm/Object/MachO.h
+++ b/llvm/include/llvm/Object/MachO.h
@@ -563,6 +563,7 @@ class MachOObjectFile : public ObjectFile {
   ArrayRef<uint8_t> getDyldInfoWeakBindOpcodes() const;
   ArrayRef<uint8_t> getDyldInfoLazyBindOpcodes() const;
   ArrayRef<uint8_t> getDyldInfoExportsTrie() const;
+  SmallVector<uint64_t> getFunctionStarts() const;
   ArrayRef<uint8_t> getUuid() const;
 
   StringRef getStringTableData() const;
@@ -689,6 +690,7 @@ class MachOObjectFile : public ObjectFile {
   const char *DataInCodeLoadCmd = nullptr;
   const char *LinkOptHintsLoadCmd = nullptr;
   const char *DyldInfoLoadCmd = nullptr;
+  const char *FuncStartsLoadCmd = nullptr;
   const char *UuidLoadCmd = nullptr;
   bool HasPageZeroSegment = false;
 };

diff  --git a/llvm/include/llvm/ObjectYAML/MachOYAML.h b/llvm/include/llvm/ObjectYAML/MachOYAML.h
index 38a7de3d6131..095377c1b824 100644
--- a/llvm/include/llvm/ObjectYAML/MachOYAML.h
+++ b/llvm/include/llvm/ObjectYAML/MachOYAML.h
@@ -122,6 +122,7 @@ struct LinkEditData {
   std::vector<NListEntry> NameList;
   std::vector<StringRef> StringTable;
   std::vector<yaml::Hex32> IndirectSymbols;
+  std::vector<yaml::Hex64> FunctionStarts;
 
   bool isEmpty() const;
 };

diff  --git a/llvm/lib/Object/MachOObjectFile.cpp b/llvm/lib/Object/MachOObjectFile.cpp
index 909a4cf4848c..85f3824aedd8 100644
--- a/llvm/lib/Object/MachOObjectFile.cpp
+++ b/llvm/lib/Object/MachOObjectFile.cpp
@@ -1303,7 +1303,6 @@ MachOObjectFile::MachOObjectFile(MemoryBufferRef Object, bool IsLittleEndian,
   }
 
   const char *DyldIdLoadCmd = nullptr;
-  const char *FuncStartsLoadCmd = nullptr;
   const char *SplitInfoLoadCmd = nullptr;
   const char *CodeSignDrsLoadCmd = nullptr;
   const char *CodeSignLoadCmd = nullptr;
@@ -4663,6 +4662,21 @@ ArrayRef<uint8_t> MachOObjectFile::getDyldInfoExportsTrie() const {
   return makeArrayRef(Ptr, DyldInfo.export_size);
 }
 
+SmallVector<uint64_t> MachOObjectFile::getFunctionStarts() const {
+  if (!FuncStartsLoadCmd)
+    return {};
+
+  auto InfoOrErr =
+      getStructOrErr<MachO::linkedit_data_command>(*this, FuncStartsLoadCmd);
+  if (!InfoOrErr)
+    return {};
+
+  MachO::linkedit_data_command Info = InfoOrErr.get();
+  SmallVector<uint64_t, 8> FunctionStarts;
+  this->ReadULEB128s(Info.dataoff, FunctionStarts);
+  return std::move(FunctionStarts);
+}
+
 ArrayRef<uint8_t> MachOObjectFile::getUuid() const {
   if (!UuidLoadCmd)
     return None;

diff  --git a/llvm/lib/ObjectYAML/MachOEmitter.cpp b/llvm/lib/ObjectYAML/MachOEmitter.cpp
index b9fad2982828..c7811520c76e 100644
--- a/llvm/lib/ObjectYAML/MachOEmitter.cpp
+++ b/llvm/lib/ObjectYAML/MachOEmitter.cpp
@@ -55,6 +55,7 @@ class MachOWriter {
   void writeStringTable(raw_ostream &OS);
   void writeExportTrie(raw_ostream &OS);
   void writeDynamicSymbolTable(raw_ostream &OS);
+  void writeFunctionStarts(raw_ostream &OS);
 
   void dumpExportEntry(raw_ostream &OS, MachOYAML::ExportEntry &Entry);
   void ZeroToOffset(raw_ostream &OS, size_t offset);
@@ -484,6 +485,7 @@ void MachOWriter::writeLinkEditData(raw_ostream &OS) {
   MachO::dyld_info_command *DyldInfoOnlyCmd = nullptr;
   MachO::symtab_command *SymtabCmd = nullptr;
   MachO::dysymtab_command *DSymtabCmd = nullptr;
+  MachO::linkedit_data_command *FunctionStartsCmd = nullptr;
   for (auto &LC : Obj.LoadCommands) {
     switch (LC.Data.load_command_data.cmd) {
     case MachO::LC_SYMTAB:
@@ -511,6 +513,11 @@ void MachOWriter::writeLinkEditData(raw_ostream &OS) {
       WriteQueue.push_back(std::make_pair(
           DSymtabCmd->indirectsymoff, &MachOWriter::writeDynamicSymbolTable));
       break;
+    case MachO::LC_FUNCTION_STARTS:
+      FunctionStartsCmd = &LC.Data.linkedit_data_command_data;
+      WriteQueue.push_back(std::make_pair(FunctionStartsCmd->dataoff,
+                                          &MachOWriter::writeFunctionStarts));
+      break;
     }
   }
 
@@ -569,6 +576,17 @@ void MachOWriter::writeDynamicSymbolTable(raw_ostream &OS) {
              sizeof(yaml::Hex32::BaseType));
 }
 
+void MachOWriter::writeFunctionStarts(raw_ostream &OS) {
+  uint64_t Addr = 0;
+  for (uint64_t NextAddr : Obj.LinkEdit.FunctionStarts) {
+    uint64_t Delta = NextAddr - Addr;
+    encodeULEB128(Delta, OS);
+    Addr = NextAddr;
+  }
+
+  OS.write('\0');
+}
+
 class UniversalWriter {
 public:
   UniversalWriter(yaml::YamlObjectFile &ObjectFile)

diff  --git a/llvm/lib/ObjectYAML/MachOYAML.cpp b/llvm/lib/ObjectYAML/MachOYAML.cpp
index f32009458110..b6f3b53a42b3 100644
--- a/llvm/lib/ObjectYAML/MachOYAML.cpp
+++ b/llvm/lib/ObjectYAML/MachOYAML.cpp
@@ -26,10 +26,10 @@ namespace llvm {
 MachOYAML::LoadCommand::~LoadCommand() = default;
 
 bool MachOYAML::LinkEditData::isEmpty() const {
-  return 0 ==
-         RebaseOpcodes.size() + BindOpcodes.size() + WeakBindOpcodes.size() +
-             LazyBindOpcodes.size() + ExportTrie.Children.size() +
-             NameList.size() + StringTable.size();
+  return 0 == RebaseOpcodes.size() + BindOpcodes.size() +
+                  WeakBindOpcodes.size() + LazyBindOpcodes.size() +
+                  ExportTrie.Children.size() + NameList.size() +
+                  StringTable.size() + FunctionStarts.size();
 }
 
 namespace yaml {
@@ -165,6 +165,7 @@ void MappingTraits<MachOYAML::LinkEditData>::mapping(
   IO.mapOptional("NameList", LinkEditData.NameList);
   IO.mapOptional("StringTable", LinkEditData.StringTable);
   IO.mapOptional("IndirectSymbols", LinkEditData.IndirectSymbols);
+  IO.mapOptional("FunctionStarts", LinkEditData.FunctionStarts);
 }
 
 void MappingTraits<MachOYAML::RebaseOpcode>::mapping(

diff  --git a/llvm/test/ObjectYAML/MachO/function_starts.yaml b/llvm/test/ObjectYAML/MachO/function_starts.yaml
new file mode 100644
index 000000000000..fe939a68a0c1
--- /dev/null
+++ b/llvm/test/ObjectYAML/MachO/function_starts.yaml
@@ -0,0 +1,186 @@
+--- !mach-o
+FileHeader:
+  magic:           0xFEEDFACF
+  cputype:         0x100000C
+  cpusubtype:      0x0
+  filetype:        0x2
+  ncmds:           15
+  sizeofcmds:      728
+  flags:           0x200085
+  reserved:        0x0
+LoadCommands:
+  - cmd:             LC_SEGMENT_64
+    cmdsize:         72
+    segname:         __PAGEZERO
+    vmaddr:          0
+    vmsize:          4294967296
+    fileoff:         0
+    filesize:        0
+    maxprot:         0
+    initprot:        0
+    nsects:          0
+    flags:           0
+  - cmd:             LC_SEGMENT_64
+    cmdsize:         232
+    segname:         __TEXT
+    vmaddr:          4294967296
+    vmsize:          16384
+    fileoff:         0
+    filesize:        16384
+    maxprot:         5
+    initprot:        5
+    nsects:          2
+    flags:           0
+    Sections:
+      - sectname:        __text
+        segname:         __TEXT
+        addr:            0x100003F80
+        size:            48
+        offset:          0x3F80
+        align:           2
+        reloff:          0x0
+        nreloc:          0
+        flags:           0x80000400
+        reserved1:       0x0
+        reserved2:       0x0
+        reserved3:       0x0
+        content:         C0035FD6FF8300D1FD7B01A9FD43009108008052E80B00B9BFC31FB8F9FFFF97E00B40B9FD7B41A9FF830091C0035FD6
+      - sectname:        __unwind_info
+        segname:         __TEXT
+        addr:            0x100003FB0
+        size:            80
+        offset:          0x3FB0
+        align:           2
+        reloff:          0x0
+        nreloc:          0
+        flags:           0x0
+        reserved1:       0x0
+        reserved2:       0x0
+        reserved3:       0x0
+        content:         010000001C000000000000001C000000000000001C00000002000000803F00003400000034000000B13F00000000000034000000030000000C0002001400020000000001040000000000000400000002
+  - cmd:             LC_SEGMENT_64
+    cmdsize:         72
+    segname:         __LINKEDIT
+    vmaddr:          4294983680
+    vmsize:          16384
+    fileoff:         16384
+    filesize:        208
+    maxprot:         1
+    initprot:        1
+    nsects:          0
+    flags:           0
+  - cmd:             LC_DYLD_CHAINED_FIXUPS
+    cmdsize:         16
+    dataoff:         16384
+    datasize:        56
+  - cmd:             LC_DYLD_EXPORTS_TRIE
+    cmdsize:         16
+    dataoff:         16440
+    datasize:        56
+  - cmd:             LC_SYMTAB
+    cmdsize:         24
+    symoff:          16504
+    nsyms:           3
+    stroff:          16552
+    strsize:         40
+  - cmd:             LC_DYSYMTAB
+    cmdsize:         80
+    ilocalsym:       0
+    nlocalsym:       0
+    iextdefsym:      0
+    nextdefsym:      3
+    iundefsym:       3
+    nundefsym:       0
+    tocoff:          0
+    ntoc:            0
+    modtaboff:       0
+    nmodtab:         0
+    extrefsymoff:    0
+    nextrefsyms:     0
+    indirectsymoff:  0
+    nindirectsyms:   0
+    extreloff:       0
+    nextrel:         0
+    locreloff:       0
+    nlocrel:         0
+  - cmd:             LC_LOAD_DYLINKER
+    cmdsize:         32
+    name:            12
+    Content:         '/usr/lib/dyld'
+    ZeroPadBytes:    7
+  - cmd:             LC_UUID
+    cmdsize:         24
+    uuid:            E1953271-0EDC-3009-9BED-635C8BB3DFE7
+  - cmd:             LC_BUILD_VERSION
+    cmdsize:         32
+    platform:        1
+    minos:           786432
+    sdk:             786688
+    ntools:          1
+    Tools:
+      - tool:            3
+        version:         46596096
+  - cmd:             LC_SOURCE_VERSION
+    cmdsize:         16
+    version:         0
+  - cmd:             LC_MAIN
+    cmdsize:         24
+    entryoff:        16260
+    stacksize:       0
+  - cmd:             LC_LOAD_DYLIB
+    cmdsize:         56
+    dylib:
+      name:            24
+      timestamp:       2
+      current_version: 85917696
+      compatibility_version: 65536
+    Content:         '/usr/lib/libSystem.B.dylib'
+    ZeroPadBytes:    6
+  - cmd:             LC_FUNCTION_STARTS
+    cmdsize:         16
+    dataoff:         16496
+    datasize:        8
+  - cmd:             LC_DATA_IN_CODE
+    cmdsize:         16
+    dataoff:         16504
+    datasize:        0
+LinkEditData:
+  NameList:
+    - n_strx:          2
+      n_type:          0xF
+      n_sect:          1
+      n_desc:          16
+      n_value:         4294967296
+    - n_strx:          22
+      n_type:          0xF
+      n_sect:          1
+      n_desc:          0
+      n_value:         4294983552
+    - n_strx:          27
+      n_type:          0xF
+      n_sect:          1
+      n_desc:          0
+      n_value:         4294983556
+  StringTable:
+    - ' '
+    - __mh_execute_header
+    - _foo
+    - _main
+    - ''
+    - ''
+    - ''
+    - ''
+    - ''
+    - ''
+    - ''
+  FunctionStarts:  [ 0x3F80, 0x3F84 ]
+...
+
+# RUN: yaml2obj %s -o=%t
+# RUN obj2yaml %t | FileCheck %s
+# CHECK: FunctionStarts:  [ 0x3F80, 0x3F84 ]
+
+# RUN: llvm-objdump --macho --function-starts %t | FileCheck %s --check-prefix=OBJDUMP-VERIFY
+# OBJDUMP-VERIFY: function_starts.yaml.tmp:
+# OBJDUMP-VERIFY: 0000000100003f80
+# OBJDUMP-VERIFY: 0000000100003f84

diff  --git a/llvm/tools/obj2yaml/macho2yaml.cpp b/llvm/tools/obj2yaml/macho2yaml.cpp
index a6339b2663e9..a32b6bf13366 100644
--- a/llvm/tools/obj2yaml/macho2yaml.cpp
+++ b/llvm/tools/obj2yaml/macho2yaml.cpp
@@ -34,6 +34,7 @@ class MachODumper {
   Error dumpLoadCommands(std::unique_ptr<MachOYAML::Object> &Y);
   void dumpLinkEdit(std::unique_ptr<MachOYAML::Object> &Y);
   void dumpRebaseOpcodes(std::unique_ptr<MachOYAML::Object> &Y);
+  void dumpFunctionStarts(std::unique_ptr<MachOYAML::Object> &Y);
   void dumpBindOpcodes(std::vector<MachOYAML::BindOpcode> &BindOpcodes,
                        ArrayRef<uint8_t> OpcodeBuffer, bool Lazy = false);
   void dumpExportTrie(std::unique_ptr<MachOYAML::Object> &Y);
@@ -353,6 +354,15 @@ void MachODumper::dumpLinkEdit(std::unique_ptr<MachOYAML::Object> &Y) {
   dumpExportTrie(Y);
   dumpSymbols(Y);
   dumpIndirectSymbols(Y);
+  dumpFunctionStarts(Y);
+}
+
+void MachODumper::dumpFunctionStarts(std::unique_ptr<MachOYAML::Object> &Y) {
+  MachOYAML::LinkEditData &LEData = Y->LinkEdit;
+
+  auto FunctionStarts = Obj.getFunctionStarts();
+  for (auto Addr : FunctionStarts)
+    LEData.FunctionStarts.push_back(Addr);
 }
 
 void MachODumper::dumpRebaseOpcodes(std::unique_ptr<MachOYAML::Object> &Y) {


        


More information about the llvm-commits mailing list