labath created this revision.
labath added reviewers: clayborg, zturner, lemo.
Herald added subscribers: arichardson, emaste.
Herald added a reviewer: espindola.

Object files generally have a "base" address, which is their preferred
address to be loaded into memory (in the sense that if they are loaded
at this address, then no runtime relocation is required). This is often
the lowest address corresponding to that object file, and various other
addresses are expressed relative to this base (relative virtual
addresses (RVAs) in PE/COFF parlor).

All three of our main object file formats already had such a concept
(it's usually needed to implement SetLoadAddress), but it was not
exposed in any way. The motivation for making this public is that the
symbol address in the breakpad format are written relative to this
address.


https://reviews.llvm.org/D55356

Files:
  include/lldb/Symbol/ObjectFile.h
  lit/Modules/ELF/basic-info.yaml
  lit/Modules/MachO/basic-info.yaml
  lit/Modules/PECOFF/basic-info.yaml
  lit/Modules/build-id-case.yaml
  lit/Modules/compressed-sections.yaml
  lit/Modules/elf-section-types.yaml
  source/Plugins/ObjectFile/Breakpad/ObjectFileBreakpad.h
  source/Plugins/ObjectFile/ELF/ObjectFileELF.cpp
  source/Plugins/ObjectFile/ELF/ObjectFileELF.h
  source/Plugins/ObjectFile/JIT/ObjectFileJIT.h
  source/Plugins/ObjectFile/Mach-O/ObjectFileMachO.cpp
  source/Plugins/ObjectFile/Mach-O/ObjectFileMachO.h
  source/Plugins/ObjectFile/PECOFF/ObjectFilePECOFF.h
  tools/lldb-test/lldb-test.cpp

Index: tools/lldb-test/lldb-test.cpp
===================================================================
--- tools/lldb-test/lldb-test.cpp
+++ tools/lldb-test/lldb-test.cpp
@@ -750,6 +750,7 @@
     Printer.formatLine("Stripped: {0}", ObjectPtr->IsStripped());
     Printer.formatLine("Type: {0}", ObjectPtr->GetType());
     Printer.formatLine("Strata: {0}", ObjectPtr->GetStrata());
+    Printer.formatLine("Base VM address: {0:x}", ObjectPtr->GetBaseFileAddress());
 
     size_t Count = Sections->GetNumSections(0);
     Printer.formatLine("Showing {0} sections", Count);
@@ -760,6 +761,7 @@
       Printer.formatLine("Index: {0}", I);
       Printer.formatLine("Name: {0}", S->GetName().GetStringRef());
       Printer.formatLine("Type: {0}", S->GetTypeAsCString());
+      Printer.formatLine("VM address: {0:x}", S->GetFileAddress());
       Printer.formatLine("VM size: {0}", S->GetByteSize());
       Printer.formatLine("File size: {0}", S->GetFileSize());
 
Index: source/Plugins/ObjectFile/PECOFF/ObjectFilePECOFF.h
===================================================================
--- source/Plugins/ObjectFile/PECOFF/ObjectFilePECOFF.h
+++ source/Plugins/ObjectFile/PECOFF/ObjectFilePECOFF.h
@@ -117,6 +117,8 @@
 
   virtual lldb_private::Address GetEntryPointAddress() override;
 
+  lldb::addr_t GetBaseFileAddress() override { return m_image_base; }
+
   ObjectFile::Type CalculateType() override;
 
   ObjectFile::Strata CalculateStrata() override;
Index: source/Plugins/ObjectFile/Mach-O/ObjectFileMachO.h
===================================================================
--- source/Plugins/ObjectFile/Mach-O/ObjectFileMachO.h
+++ source/Plugins/ObjectFile/Mach-O/ObjectFileMachO.h
@@ -106,6 +106,8 @@
 
   lldb_private::Address GetHeaderAddress() override;
 
+  lldb::addr_t GetBaseFileAddress() override;
+
   uint32_t GetNumThreadContexts() override;
 
   std::string GetIdentifierString() override;
Index: source/Plugins/ObjectFile/Mach-O/ObjectFileMachO.cpp
===================================================================
--- source/Plugins/ObjectFile/Mach-O/ObjectFileMachO.cpp
+++ source/Plugins/ObjectFile/Mach-O/ObjectFileMachO.cpp
@@ -5353,6 +5353,12 @@
   return header_addr;
 }
 
+addr_t ObjectFileMachO::GetBaseFileAddress() {
+  if (Section *sect = GetMachHeaderSection())
+    return sect->GetFileAddress();
+  return LLDB_INVALID_ADDRESS;
+}
+
 uint32_t ObjectFileMachO::GetNumThreadContexts() {
   ModuleSP module_sp(GetModule());
   if (module_sp) {
Index: source/Plugins/ObjectFile/JIT/ObjectFileJIT.h
===================================================================
--- source/Plugins/ObjectFile/JIT/ObjectFileJIT.h
+++ source/Plugins/ObjectFile/JIT/ObjectFileJIT.h
@@ -91,6 +91,8 @@
 
   lldb_private::Address GetHeaderAddress() override;
 
+  lldb::addr_t GetBaseFileAddress() override { return LLDB_INVALID_ADDRESS; }
+
   ObjectFile::Type CalculateType() override;
 
   ObjectFile::Strata CalculateStrata() override;
Index: source/Plugins/ObjectFile/ELF/ObjectFileELF.h
===================================================================
--- source/Plugins/ObjectFile/ELF/ObjectFileELF.h
+++ source/Plugins/ObjectFile/ELF/ObjectFileELF.h
@@ -134,6 +134,8 @@
 
   lldb_private::Address GetEntryPointAddress() override;
 
+  lldb::addr_t GetBaseFileAddress() override;
+
   ObjectFile::Type CalculateType() override;
 
   ObjectFile::Strata CalculateStrata() override;
Index: source/Plugins/ObjectFile/ELF/ObjectFileELF.cpp
===================================================================
--- source/Plugins/ObjectFile/ELF/ObjectFileELF.cpp
+++ source/Plugins/ObjectFile/ELF/ObjectFileELF.cpp
@@ -805,21 +805,10 @@
     SectionList *section_list = GetSectionList();
     if (section_list) {
       if (!value_is_offset) {
-        bool found_offset = false;
-        for (size_t i = 1, count = GetProgramHeaderCount(); i <= count; ++i) {
-          const elf::ELFProgramHeader *header = GetProgramHeaderByIndex(i);
-          if (header == nullptr)
-            continue;
-
-          if (header->p_type != PT_LOAD || header->p_offset != 0)
-            continue;
-
-          value = value - header->p_vaddr;
-          found_offset = true;
-          break;
-        }
-        if (!found_offset)
+        addr_t base = GetBaseFileAddress();
+        if (base == LLDB_INVALID_ADDRESS)
           return false;
+        value -= base;
       }
 
       const size_t num_sections = section_list->GetSize();
@@ -1057,6 +1046,20 @@
   return m_entry_point_address;
 }
 
+addr_t ObjectFileELF::GetBaseFileAddress() {
+  for (size_t i = 1, count = GetProgramHeaderCount(); i <= count; ++i) {
+    const elf::ELFProgramHeader *header = GetProgramHeaderByIndex(i);
+    if (header == nullptr)
+      continue;
+
+    if (header->p_type != PT_LOAD || header->p_offset != 0)
+      continue;
+
+    return header->p_vaddr;
+  }
+  return LLDB_INVALID_ADDRESS;
+}
+
 //----------------------------------------------------------------------
 // ParseDependentModules
 //----------------------------------------------------------------------
Index: source/Plugins/ObjectFile/Breakpad/ObjectFileBreakpad.h
===================================================================
--- source/Plugins/ObjectFile/Breakpad/ObjectFileBreakpad.h
+++ source/Plugins/ObjectFile/Breakpad/ObjectFileBreakpad.h
@@ -85,6 +85,8 @@
 
   uint32_t GetDependentModules(FileSpecList &files) override { return 0; }
 
+  lldb::addr_t GetBaseFileAddress() override { return LLDB_INVALID_ADDRESS; }
+
   Type CalculateType() override { return eTypeDebugInfo; }
 
   Strata CalculateStrata() override { return eStrataUser; }
Index: lit/Modules/elf-section-types.yaml
===================================================================
--- lit/Modules/elf-section-types.yaml
+++ lit/Modules/elf-section-types.yaml
@@ -6,23 +6,15 @@
 
 # CHECK: Name: .debug_info
 # CHECK-NEXT: Type: dwarf-info
-# CHECK-NEXT: VM size: 0
-# CHECK-NEXT: File size: 8
 
 # CHECK: Name: .debug_types
 # CHECK-NEXT: Type: dwarf-types
-# CHECK-NEXT: VM size: 0
-# CHECK-NEXT: File size: 8
 
 # CHECK: Name: .debug_names
 # CHECK-NEXT: Type: dwarf-names
-# CHECK-NEXT: VM size: 0
-# CHECK-NEXT: File size: 8
 
 # CHECK: Name: .gnu_debugaltlink
 # CHECK-NEXT: Type: dwarf-gnu-debugaltlink
-# CHECK-NEXT: VM size: 0
-# CHECK-NEXT: File size: 8
 
 # CHECK: Name: __codesection
 # CHECK-NEXT: Type: code
Index: lit/Modules/compressed-sections.yaml
===================================================================
--- lit/Modules/compressed-sections.yaml
+++ lit/Modules/compressed-sections.yaml
@@ -19,6 +19,7 @@
 
 # CHECK: Name: .hello_elf
 # CHECK-NEXT: Type: regular
+# CHECK-NEXT: VM address: 0
 # CHECK-NEXT: VM size: 0
 # CHECK-NEXT: File size: 28
 # CHECK-NEXT: Data:
@@ -26,6 +27,7 @@
 
 # CHECK: Name: .bogus
 # CHECK-NEXT: Type: regular
+# CHECK-NEXT: VM address: 0
 # CHECK-NEXT: VM size: 0
 # CHECK-NEXT: File size: 8
 # CHECK-NEXT: Data: ()
Index: lit/Modules/build-id-case.yaml
===================================================================
--- lit/Modules/build-id-case.yaml
+++ lit/Modules/build-id-case.yaml
@@ -6,6 +6,7 @@
 
 # CHECK: Name: .debug_frame
 # CHECK-NEXT: Type: dwarf-frame
+# CHECK-NEXT: VM address: 0
 # CHECK-NEXT: VM size: 0
 # CHECK-NEXT: File size: 8
 
Index: lit/Modules/PECOFF/basic-info.yaml
===================================================================
--- /dev/null
+++ lit/Modules/PECOFF/basic-info.yaml
@@ -0,0 +1,86 @@
+# RUN: yaml2obj %s > %t
+# RUN: lldb-test object-file %t | FileCheck %s
+
+# CHECK: Plugin name: pe-coff
+# CHECK: Architecture: x86_64-pc-windows-msvc
+# CHECK: UUID: 
+# CHECK: Executable: true
+# CHECK: Stripped: false
+# CHECK: Type: executable
+# CHECK: Strata: user
+# CHECK: Base VM address: 0x40000000
+
+--- !COFF
+OptionalHeader:  
+  AddressOfEntryPoint: 4096
+  ImageBase:       1073741824
+  SectionAlignment: 4096
+  FileAlignment:   512
+  MajorOperatingSystemVersion: 6
+  MinorOperatingSystemVersion: 0
+  MajorImageVersion: 0
+  MinorImageVersion: 0
+  MajorSubsystemVersion: 6
+  MinorSubsystemVersion: 0
+  Subsystem:       IMAGE_SUBSYSTEM_WINDOWS_CUI
+  DLLCharacteristics: [ IMAGE_DLL_CHARACTERISTICS_HIGH_ENTROPY_VA, IMAGE_DLL_CHARACTERISTICS_DYNAMIC_BASE, IMAGE_DLL_CHARACTERISTICS_NX_COMPAT, IMAGE_DLL_CHARACTERISTICS_TERMINAL_SERVER_AWARE ]
+  SizeOfStackReserve: 1048576
+  SizeOfStackCommit: 4096
+  SizeOfHeapReserve: 1048576
+  SizeOfHeapCommit: 4096
+  ExportTable:     
+    RelativeVirtualAddress: 0
+    Size:            0
+  ImportTable:     
+    RelativeVirtualAddress: 0
+    Size:            0
+  ResourceTable:   
+    RelativeVirtualAddress: 0
+    Size:            0
+  ExceptionTable:  
+    RelativeVirtualAddress: 0
+    Size:            0
+  CertificateTable: 
+    RelativeVirtualAddress: 0
+    Size:            0
+  BaseRelocationTable: 
+    RelativeVirtualAddress: 0
+    Size:            0
+  Debug:           
+    RelativeVirtualAddress: 8192
+    Size:            28
+  Architecture:    
+    RelativeVirtualAddress: 0
+    Size:            0
+  GlobalPtr:       
+    RelativeVirtualAddress: 0
+    Size:            0
+  TlsTable:        
+    RelativeVirtualAddress: 0
+    Size:            0
+  LoadConfigTable: 
+    RelativeVirtualAddress: 0
+    Size:            0
+  BoundImport:     
+    RelativeVirtualAddress: 0
+    Size:            0
+  IAT:             
+    RelativeVirtualAddress: 0
+    Size:            0
+  DelayImportDescriptor: 
+    RelativeVirtualAddress: 0
+    Size:            0
+  ClrRuntimeHeader: 
+    RelativeVirtualAddress: 0
+    Size:            0
+header:          
+  Machine:         IMAGE_FILE_MACHINE_AMD64
+  Characteristics: [ IMAGE_FILE_EXECUTABLE_IMAGE, IMAGE_FILE_LARGE_ADDRESS_AWARE ]
+sections:        
+  - Name:            .text
+    Characteristics: [ IMAGE_SCN_CNT_CODE, IMAGE_SCN_MEM_EXECUTE, IMAGE_SCN_MEM_READ ]
+    VirtualAddress:  1073745920
+    VirtualSize:     1
+    SectionData:     C3
+symbols:         []
+...
Index: lit/Modules/MachO/basic-info.yaml
===================================================================
--- /dev/null
+++ lit/Modules/MachO/basic-info.yaml
@@ -0,0 +1,217 @@
+# RUN: yaml2obj %s > %t
+# RUN: lldb-test object-file %t | FileCheck %s
+
+# CHECK: Plugin name: mach-o
+# CHECK: Architecture: x86_64-apple-macosx10.4.0
+# CHECK: Executable: true
+# CHECK: Stripped: true
+# CHECK: Type: executable
+# CHECK: Strata: user
+# CHECK: Base VM address: 0x100000000
+
+--- !mach-o
+FileHeader:      
+  magic:           0xFEEDFACF
+  cputype:         0x01000007
+  cpusubtype:      0x00000003
+  filetype:        0x00000002
+  ncmds:           12
+  sizeofcmds:      728
+  flags:           0x00000085
+  reserved:        0x00000000
+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:         312
+    segname:         __TEXT
+    vmaddr:          4294967296
+    vmsize:          4096
+    fileoff:         0
+    filesize:        4096
+    maxprot:         7
+    initprot:        5
+    nsects:          3
+    flags:           0
+    Sections:        
+      - sectname:        __text
+        segname:         __TEXT
+        addr:            0x0000000100000F30
+        size:            22
+        offset:          0x00000F30
+        align:           4
+        reloff:          0x00000000
+        nreloc:          0
+        flags:           0x80000400
+        reserved1:       0x00000000
+        reserved2:       0x00000000
+        reserved3:       0x00000000
+      - sectname:        __unwind_info
+        segname:         __TEXT
+        addr:            0x0000000100000F48
+        size:            76
+        offset:          0x00000F48
+        align:           2
+        reloff:          0x00000000
+        nreloc:          0
+        flags:           0x00000000
+        reserved1:       0x00000000
+        reserved2:       0x00000000
+        reserved3:       0x00000000
+      - sectname:        __eh_frame
+        segname:         __TEXT
+        addr:            0x0000000100000F98
+        size:            104
+        offset:          0x00000F98
+        align:           3
+        reloff:          0x00000000
+        nreloc:          0
+        flags:           0x0000000B
+        reserved1:       0x00000000
+        reserved2:       0x00000000
+        reserved3:       0x00000000
+  - cmd:             LC_SEGMENT_64
+    cmdsize:         72
+    segname:         __LINKEDIT
+    vmaddr:          4294971392
+    vmsize:          4096
+    fileoff:         4096
+    filesize:        184
+    maxprot:         7
+    initprot:        1
+    nsects:          0
+    flags:           0
+  - cmd:             LC_DYLD_INFO_ONLY
+    cmdsize:         48
+    rebase_off:      4096
+    rebase_size:     8
+    bind_off:        4104
+    bind_size:       8
+    weak_bind_off:   0
+    weak_bind_size:  0
+    lazy_bind_off:   0
+    lazy_bind_size:  0
+    export_off:      4112
+    export_size:     64
+  - cmd:             LC_SYMTAB
+    cmdsize:         24
+    symoff:          4184
+    nsyms:           3
+    stroff:          4232
+    strsize:         48
+  - 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:  4232
+    nindirectsyms:   0
+    extreloff:       0
+    nextrel:         0
+    locreloff:       0
+    nlocrel:         0
+  - cmd:             LC_LOAD_DYLINKER
+    cmdsize:         32
+    name:            12
+    PayloadString:   '/usr/lib/dyld'
+    ZeroPadBytes:    7
+  - cmd:             LC_VERSION_MIN_MACOSX
+    cmdsize:         16
+    version:         656384
+    sdk:             656384
+  - cmd:             LC_SOURCE_VERSION
+    cmdsize:         16
+    version:         0
+  - cmd:             LC_MAIN
+    cmdsize:         24
+    entryoff:        3888
+    stacksize:       0
+  - cmd:             LC_FUNCTION_STARTS
+    cmdsize:         16
+    dataoff:         4176
+    datasize:        8
+  - cmd:             LC_DATA_IN_CODE
+    cmdsize:         16
+    dataoff:         4184
+    datasize:        0
+LinkEditData:    
+  RebaseOpcodes:   
+    - Opcode:          REBASE_OPCODE_DONE
+      Imm:             0
+  BindOpcodes:     
+    - Opcode:          BIND_OPCODE_DONE
+      Imm:             0
+      Symbol:          ''
+  ExportTrie:      
+    TerminalSize:    0
+    NodeOffset:      0
+    Name:            ''
+    Flags:           0x0000000000000000
+    Address:         0x0000000000000000
+    Other:           0x0000000000000000
+    ImportName:      ''
+    Children:        
+      - TerminalSize:    2
+        NodeOffset:      48
+        Name:            __mh_execute_header
+        Flags:           0x0000000000000000
+        Address:         0x0000000000000000
+        Other:           0x0000000000000000
+        ImportName:      ''
+      - TerminalSize:    3
+        NodeOffset:      52
+        Name:            start
+        Flags:           0x0000000000000000
+        Address:         0x0000000000000F30
+        Other:           0x0000000000000000
+        ImportName:      ''
+      - TerminalSize:    3
+        NodeOffset:      57
+        Name:            dyld_stub_binder
+        Flags:           0x0000000000000000
+        Address:         0x0000000000000F40
+        Other:           0x0000000000000000
+        ImportName:      ''
+  NameList:        
+    - n_strx:          2
+      n_type:          0x0F
+      n_sect:          1
+      n_desc:          16
+      n_value:         4294967296
+    - n_strx:          22
+      n_type:          0x0F
+      n_sect:          1
+      n_desc:          0
+      n_value:         4294971200
+    - n_strx:          39
+      n_type:          0x0F
+      n_sect:          1
+      n_desc:          0
+      n_value:         4294971184
+  StringTable:     
+    - ' '
+    - __mh_execute_header
+    - dyld_stub_binder
+    - start
+    - ''
+    - ''
+    - ''
+...
Index: lit/Modules/ELF/basic-info.yaml
===================================================================
--- /dev/null
+++ lit/Modules/ELF/basic-info.yaml
@@ -0,0 +1,27 @@
+# REQUIRES: lld
+
+# RUN: yaml2obj %s > %t.o
+# RUN: ld.lld %t.o -o %t -image-base 0x47000
+# RUN: lldb-test object-file %t | FileCheck %s
+
+# CHECK: Plugin name: elf
+# CHECK: Architecture: x86_64--
+# CHECK: Executable: true
+# CHECK: Stripped: false
+# CHECK: Type: executable
+# CHECK: Strata: user
+# CHECK: Base VM address: 0x47000
+
+--- !ELF
+FileHeader:      
+  Class:           ELFCLASS64
+  Data:            ELFDATA2LSB
+  Type:            ET_REL
+  Machine:         EM_X86_64
+Sections:        
+  - Name:            .text
+    Type:            SHT_PROGBITS
+    Flags:           [ SHF_ALLOC, SHF_EXECINSTR ]
+    AddressAlign:    0x0000000000000010
+    Content:         554889E55DC3
+...
Index: include/lldb/Symbol/ObjectFile.h
===================================================================
--- include/lldb/Symbol/ObjectFile.h
+++ include/lldb/Symbol/ObjectFile.h
@@ -566,6 +566,11 @@
     return Address(m_memory_addr);
   }
 
+  /// Returns the base file address of an object file (also known as the
+  /// preferred load address or image base address). This is typically the file
+  /// address of the first section in the file.
+  virtual lldb::addr_t GetBaseFileAddress() = 0;
+
   virtual uint32_t GetNumThreadContexts() { return 0; }
 
   //------------------------------------------------------------------
_______________________________________________
lldb-commits mailing list
lldb-commits@lists.llvm.org
http://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits

Reply via email to