[llvm-commits] [PATCH] Object File Library

Chris Lattner clattner at apple.com
Sat Jan 15 23:06:43 PST 2011


On Dec 18, 2010, at 4:58 PM, Michael Spencer wrote:

> On Sat, Dec 18, 2010 at 4:55 PM, Chris Lattner <clattner at apple.com> wrote:
>> 
>> On Dec 15, 2010, at 6:48 PM, Michael Spencer wrote:
>> 
>>> On Mon, Nov 22, 2010 at 8:00 PM, Michael Spencer <bigcheesegs at gmail.com> wrote:
>>>> On Thu, Nov 11, 2010 at 9:23 PM, Michael Spencer <bigcheesegs at gmail.com> wrote:
>>>>> Attached are updated patches to be reviewed. I've split them up into
>>>>> the generic API, the COFF and ELF implementations, tool changes, and
>>>>> tests.
>> Hi Michael,
>> 
>> Can you resend the latest version of the patches?
>> 
>> -Chris
> 
> Attached.

Sorry for the delay, here are some general comments.  I don't feel that I can do a good job reviewing the design (because I don't really understand all the implications), but you clearly have a plan. :)

Patch #1 (coff stuff):

+++ b/lib/Object/COFFObjectFile.cpp
@@ -0,0 +1,369 @@
+//===- COFFObjectFile.h - COFF object file implementation -------*- C++ -*-===//

File header wrong again...

+namespace {

Please make the anonymous namespace minimally wrap the types in it.  I'd prefer to have a new anon namespace for each type, but that's up to you.
http://llvm.org/docs/CodingStandards.html#micro_anonns

+const coff_section *COFFObjectFile::getSection(std::size_t index) const {
+  if (index > 0 && index <= Header->NumberOfSections)
+    return SectionTable + (index - 1);
+  else
+    return 0;

Very minor, but there is no need for else after the return (likewise elsewhere).

+// static_assert(sizeof(coff_file_header) == 20,
+//   "coff_file_header must be a packed pod of 20 bytes!");

You can do this with an extern array:

extern char coff_layout_static_assert[sizeof(foo) == 20 ? 1 : -1];


Patch #2 (elf stuff):

+++ b/lib/Object/ELFObjectFile.cpp
@@ -0,0 +1,702 @@
+//===- ELFObjectFile.h - ELF object file implementation ---------*- C++ -*-===//

Comment wrong again :)

Same comment about anon namespaces.


+template<support::endianness target_endianness>
+struct Elf_Shdr_Base<target_endianness, false> {
+  LLVM_ELF_IMPORT_TYPES(target_endianness, false)
+  Elf_Word sh_name;     // Section name (index into string table)
+  Elf_Word sh_type;     // Section type (SHT_*)
+  Elf_Word sh_flags;    // Section flags (SHF_*)
+  Elf_Addr sh_addr;     // Address where section is to be loaded
...
+template<support::endianness target_endianness>
+struct Elf_Shdr_Base<target_endianness, true> {
+  LLVM_ELF_IMPORT_TYPES(target_endianness, true)
+  Elf_Word  sh_name;     // Section name (index into string table)
+  Elf_Word  sh_type;     // Section type (SHT_*)
+  Elf_Xword sh_flags;    // Section flags (SHF_*)
+  Elf_Addr  sh_addr;     // Address where section is to be loaded


Instead of doing this with explicit specializations like this, I'd suggest defining a helper type like this:

template<bool is64Bits>
struct ElfArchSpecificTypes;

template<> struct ElfArchSpecificTypes<false> {
  typedef Elf_Word PtrSize_Word;
};
template<> struct ElfArchSpecificTypes<true> {
  typedef Elf_Xword PtrSize_Word;
};

THis allows you to define Elf_Shdr_Base in one copy, making the fields that change something like:

template<support::endianness target_endianness, bool is64Bits>
struct Elf_Shdr_Base {
  LLVM_ELF_IMPORT_TYPES(target_endianness, is64Bit)
  Elf_Word sh_name;     // Section name (index into string table)
  Elf_Word sh_type;     // Section type (SHT_*)
  typename ElfArchSpecificTypes<is64Bit>::PtrSize_Word sh_flags;    // Section flags (SHF_*)
  Elf_Addr sh_addr;     // Address where section is to be loaded


This also allows you to eliminate the icky LLVM_ELF_IMPORT_TYPES macro.  In fact it looks like you've partially done this with ELFDataTypeTypedefHelper, why not move the "pointer sized word" concept into it?

Another way to make eliminate the LLVM_ELF_IMPORT_TYPES macro is to just have Elf_Shdr_Base (for example) inherit from ELFDataTypeTypedefHelper.

+    report_fatal_error("Sybol name offset outside of string table!");

typo "Symbol".

+    if (Ident.first == ELF::ELFCLASS32 && Ident.second == ELF::ELFDATA2LSB)
+      return new ELFObjectFile<support::little, false>(Object);
+    else if (Ident.first == ELF::ELFCLASS32 && Ident.second == ELF::ELFDATA2MSB)
+      return new ELFObjectFile<support::big, false>(Object);
+    else if (Ident.first == ELF::ELFCLASS64 && Ident.second == ELF::ELFDATA2LSB)
+      return new ELFObjectFile<support::little, true>(Object);
+    else if (Ident.first == ELF::ELFCLASS64 && Ident.second == ELF::ELFDATA2MSB)
+      return new ELFObjectFile<support::big, true>(Object);
+    else
+      // FIXME: Proper error handling.
+      report_fatal_error("Not an ELF object file!");

No "else" needed after return.


Patch #3: NM Stuff

Looks reasonable to me!

Patch #4: ObjDump

+++ b/tools/llvm-objdump/Makefile
@@ -0,0 +1,17 @@
+##===- tools/llvm-nm/Makefile ------------------------------*- Makefile -*-===##

Please update file headers.

+++ b/tools/llvm-objdump/llvm-objdump.cpp
@@ -0,0 +1,257 @@
+//===-- llvm-nm.cpp - Symbol table dumping utility for llvm ---------------===//

Please update file headers :)


+  const unsigned OutputSize = (15 * 3) + 1;
+  char output[OutputSize];

I'm pretty sure that this is a VLA in C++, please avoid this for portability.  Maybe make OutputSize an enum?


+  for (ObjectFile::section_iterator i = Obj->begin_sections(),
+                                    e = Obj->end_sections();
+                                    i != e; ++i) {
+    if (i->isText()) {


Please use: "if (!i->isText()) continue;" to reduce indentation of the loop body.


Patch #5: testcases

Looks good!

Please make the changes above and commit whenever you'd like to Michael.  This looks like great work!

-Chris


 








More information about the llvm-commits mailing list