From: Shankar Easwaran Date: Tue, 13 Nov 2012 18:38:42 +0000 (+0000) Subject: Adding changes to support GNU style archive library reading X-Git-Url: http://plrg.eecs.uci.edu/git/?p=oota-llvm.git;a=commitdiff_plain;h=206252cc9f5509b27aa0761c677fdee8daff001c Adding changes to support GNU style archive library reading git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@167853 91177308-0d34-0410-b5e6-96231b3b80d8 --- diff --git a/include/llvm/Object/Archive.h b/include/llvm/Object/Archive.h index f3d824960c2..9cd587195a4 100644 --- a/include/llvm/Object/Archive.h +++ b/include/llvm/Object/Archive.h @@ -122,6 +122,16 @@ public: Archive(MemoryBuffer *source, error_code &ec); + enum Kind { + K_GNU, + K_BSD, + K_COFF + }; + + Kind kind() const { + return Format; + } + child_iterator begin_children(bool skip_internal = true) const; child_iterator end_children() const; @@ -133,9 +143,13 @@ public: return v->isArchive(); } + // check if a symbol is in the archive + child_iterator findSym(StringRef name) const; + private: child_iterator SymbolTable; child_iterator StringTable; + Kind Format; }; } diff --git a/lib/Object/Archive.cpp b/lib/Object/Archive.cpp index 2a5951ada50..b55dab8f85d 100644 --- a/lib/Object/Archive.cpp +++ b/lib/Object/Archive.cpp @@ -122,7 +122,14 @@ error_code Archive::Child::getName(StringRef &Result) const { + sizeof(ArchiveMemberHeader) + Parent->StringTable->getSize())) return object_error::parse_failed; - Result = addr; + + // GNU long file names end with a /. + if (Parent->kind() == K_GNU) { + StringRef::size_type End = StringRef(addr).find('/'); + Result = StringRef(addr, End); + } else { + Result = addr; + } return object_error::success; } else if (name.startswith("#1/")) { APInt name_size; @@ -187,15 +194,52 @@ Archive::Archive(MemoryBuffer *source, error_code &ec) child_iterator i = begin_children(false); child_iterator e = end_children(); - if (i != e) ++i; // Nobody cares about the first member. - if (i != e) { - SymbolTable = i; - ++i; - } - if (i != e) { - StringTable = i; - } + StringRef name; + if ((ec = i->getName(name))) + return; + // Below is the pattern that is used to figure out the archive format + // GNU archive format + // First member : / (points to the symbol table ) + // Second member : // (may exist, if it exists, points to the string table) + // Note : The string table is used if the filename exceeds 15 characters + // BSD archive format + // First member : __.SYMDEF (points to the symbol table) + // There is no string table, if the filename exceeds 15 characters or has a + // embedded space, the filename has #1/, The size represents the size + // of the filename that needs to be read after the archive header + // COFF archive format + // First member : / + // Second member : / (provides a directory of symbols) + // Third member : // contains the string table, this is present even if the + // string table is empty + if (name == "/") { + SymbolTable = i; + StringTable = e; + if (i != e) ++i; + if ((ec = i->getName(name))) + return; + if (name[0] != '/') { + Format = K_GNU; + } else if ((name.size() > 1) && (name == "//")) { + Format = K_GNU; + StringTable = i; + ++i; + } else { + Format = K_COFF; + if (i != e) { + SymbolTable = i; + ++i; + } + if (i != e) { + StringTable = i; + } + } + } else if (name == "__.SYMDEF") { + Format = K_BSD; + SymbolTable = i; + StringTable = e; + } ec = object_error::success; } @@ -222,17 +266,28 @@ error_code Archive::Symbol::getName(StringRef &Result) const { error_code Archive::Symbol::getMember(child_iterator &Result) const { const char *buf = Parent->SymbolTable->getBuffer()->getBufferStart(); - uint32_t member_count = *reinterpret_cast(buf); const char *offsets = buf + 4; - buf += 4 + (member_count * 4); // Skip offsets. - const char *indicies = buf + 4; - - uint16_t offsetindex = - *(reinterpret_cast(indicies) - + SymbolIndex); - - uint32_t offset = *(reinterpret_cast(offsets) - + (offsetindex - 1)); + uint32_t offset = 0; + if (Parent->kind() == K_GNU) { + offset = *(reinterpret_cast(offsets) + + SymbolIndex); + } else if (Parent->kind() == K_BSD) { + assert("BSD format is not supported"); + } else { + uint32_t member_count = 0; + member_count = *reinterpret_cast(buf); + buf += 4 + (member_count * 4); // Skip offsets. + const char *indicies = buf + 4; + uint16_t offsetindex = + *(reinterpret_cast(indicies) + + SymbolIndex); + uint32_t *offsetaddr = + (uint32_t *)(reinterpret_cast(offsets) + + (offsetindex - 1)); + assert((const char *)offsetaddr < + Parent->SymbolTable->getBuffer()->getBufferEnd()); + offset = *(offsetaddr); + } const char *Loc = Parent->getData().begin() + offset; size_t Size = sizeof(ArchiveMemberHeader) + @@ -253,10 +308,20 @@ Archive::Symbol Archive::Symbol::getNext() const { Archive::symbol_iterator Archive::begin_symbols() const { const char *buf = SymbolTable->getBuffer()->getBufferStart(); - uint32_t member_count = *reinterpret_cast(buf); - buf += 4 + (member_count * 4); // Skip offsets. - uint32_t symbol_count = *reinterpret_cast(buf); - buf += 4 + (symbol_count * 2); // Skip indices. + if (kind() == K_GNU) { + uint32_t symbol_count = 0; + symbol_count = *reinterpret_cast(buf); + buf += sizeof(uint32_t) + (symbol_count * (sizeof(uint32_t))); + } else if (kind() == K_BSD) { + assert("BSD archive format is not supported"); + } else { + uint32_t member_count = 0; + uint32_t symbol_count = 0; + member_count = *reinterpret_cast(buf); + buf += 4 + (member_count * 4); // Skip offsets. + symbol_count = *reinterpret_cast(buf); + buf += 4 + (symbol_count * 2); // Skip indices. + } uint32_t string_start_offset = buf - SymbolTable->getBuffer()->getBufferStart(); return symbol_iterator(Symbol(this, 0, string_start_offset)); @@ -264,9 +329,36 @@ Archive::symbol_iterator Archive::begin_symbols() const { Archive::symbol_iterator Archive::end_symbols() const { const char *buf = SymbolTable->getBuffer()->getBufferStart(); - uint32_t member_count = *reinterpret_cast(buf); - buf += 4 + (member_count * 4); // Skip offsets. - uint32_t symbol_count = *reinterpret_cast(buf); + uint32_t symbol_count = 0; + if (kind() == K_GNU) { + symbol_count = *reinterpret_cast(buf); + buf += sizeof(uint32_t) + (symbol_count * (sizeof(uint32_t))); + } else if (kind() == K_BSD) { + assert("BSD archive format is not supported"); + } else { + uint32_t member_count = 0; + member_count = *reinterpret_cast(buf); + buf += 4 + (member_count * 4); // Skip offsets. + symbol_count = *reinterpret_cast(buf); + } return symbol_iterator( Symbol(this, symbol_count, 0)); } + +Archive::child_iterator Archive::findSym(StringRef name) const { + Archive::symbol_iterator bs = begin_symbols(); + Archive::symbol_iterator es = end_symbols(); + Archive::child_iterator result; + + StringRef symname; + for (; bs != es; ++bs) { + if (bs->getName(symname)) + return end_children(); + if (symname == name) { + if (bs->getMember(result)) + return end_children(); + return result; + } + } + return end_children(); +} diff --git a/test/Object/Inputs/coff_archive.lib b/test/Object/Inputs/coff_archive.lib new file mode 100755 index 00000000000..e079991bfba Binary files /dev/null and b/test/Object/Inputs/coff_archive.lib differ diff --git a/test/Object/Inputs/liblong_filenames.a b/test/Object/Inputs/liblong_filenames.a new file mode 100644 index 00000000000..368d665c94e Binary files /dev/null and b/test/Object/Inputs/liblong_filenames.a differ diff --git a/test/Object/Inputs/libsimple_archive.a b/test/Object/Inputs/libsimple_archive.a new file mode 100644 index 00000000000..6e232e3e3cf Binary files /dev/null and b/test/Object/Inputs/libsimple_archive.a differ diff --git a/test/Object/archive-long-index.test b/test/Object/archive-long-index.test new file mode 100644 index 00000000000..d0fb19cd8de --- /dev/null +++ b/test/Object/archive-long-index.test @@ -0,0 +1,40 @@ +# +# Check if the index is appearing properly in the output file +# +RUN: llvm-nm -s %p/Inputs/liblong_filenames.a | FileCheck -check-prefix=CHECKIDX %s + +CHECKIDX: Archive map +CHECKIDX: abcdefghijklmnopqrstuvwxyz12345678 in 1.o +CHECKIDX: main in 1.o +CHECKIDX: fn1 in 2.o +CHECKIDX: fn3 in 3.o +CHECKIDX: fn1 in 3.o +CHECKIDX: shankar in 4.o +CHECKIDX: a in 5.o +CHECKIDX: b in 6.o +CHECKIDX: a in abcdefghijklmnopqrstuvwxyz1.o +CHECKIDX: b in abcdefghijklmnopqrstuvwxyz2.o +CHECKIDX: bda in abcdefghijklmnopqrstuvwxyz2.o +CHECKIDX: b in abcdefghijklmnopq.o +CHECKIDX: 1.o: +CHECKIDX: 00000000 D abcdefghijklmnopqrstuvwxyz12345678 +CHECKIDX: U bda +CHECKIDX: 00000000 T main +CHECKIDX: 2.o: +CHECKIDX: 00000000 T fn1 +CHECKIDX: 3.o: +CHECKIDX: 0000000b T fn1 +CHECKIDX: 00000000 T fn3 +CHECKIDX: 4.o: +CHECKIDX: C shankar +CHECKIDX: 5.o: +CHECKIDX: C a +CHECKIDX: 6.o: +CHECKIDX: C b +CHECKIDX: abcdefghijklmnopqrstuvwxyz1.o: +CHECKIDX: C a +CHECKIDX: abcdefghijklmnopqrstuvwxyz2.o: +CHECKIDX: C b +CHECKIDX: 00000000 T bda +CHECKIDX: abcdefghijklmnopq.o: +CHECKIDX: C b diff --git a/test/Object/coff-archive.test b/test/Object/coff-archive.test new file mode 100644 index 00000000000..fc968bb944c --- /dev/null +++ b/test/Object/coff-archive.test @@ -0,0 +1,225 @@ +# +# Check if the index is appearing properly in the output file +# +RUN: llvm-nm -s %p/Inputs/coff_archive.lib | FileCheck -check-prefix=CHECKIDX %s + +CHECKIDX: Archive map +CHECKIDX: ??0invalid_argument@std@@QAE@PBD@Z in Debug\mymath.obj +CHECKIDX: ??0logic_error@std@@QAE@PBD@Z in Debug\mymath.obj +CHECKIDX: ??1invalid_argument@std@@UAE@XZ in Debug\mymath.obj +CHECKIDX: ??1logic_error@std@@UAE@XZ in Debug\mymath.obj +CHECKIDX: ??_7invalid_argument@std@@6B@ in Debug\mymath.obj +CHECKIDX: ??_7logic_error@std@@6B@ in Debug\mymath.obj +CHECKIDX: ??_C@_0BC@IHENMCGI@b?5cannot?5be?5zero?$CB?$AA@ in Debug\mymath.obj +CHECKIDX: ??_Ginvalid_argument@std@@UAEPAXI@Z in Debug\mymath.obj +CHECKIDX: ??_Glogic_error@std@@UAEPAXI@Z in Debug\mymath.obj +CHECKIDX: ??_R0?AVexception@std@@@8 in Debug\mymath.obj +CHECKIDX: ??_R0?AVinvalid_argument@std@@@8 in Debug\mymath.obj +CHECKIDX: ??_R0?AVlogic_error@std@@@8 in Debug\mymath.obj +CHECKIDX: ??_R0PAVexception@std@@@8 in Debug\mymath.obj +CHECKIDX: ??_R0PAVinvalid_argument@std@@@8 in Debug\mymath.obj +CHECKIDX: ??_R0PAVlogic_error@std@@@8 in Debug\mymath.obj +CHECKIDX: ??_R0PAX@8 in Debug\mymath.obj +CHECKIDX: ??_R1A@?0A@EA@exception@std@@8 in Debug\mymath.obj +CHECKIDX: ??_R1A@?0A@EA@invalid_argument@std@@8 in Debug\mymath.obj +CHECKIDX: ??_R1A@?0A@EA@logic_error@std@@8 in Debug\mymath.obj +CHECKIDX: ??_R2exception@std@@8 in Debug\mymath.obj +CHECKIDX: ??_R2invalid_argument@std@@8 in Debug\mymath.obj +CHECKIDX: ??_R2logic_error@std@@8 in Debug\mymath.obj +CHECKIDX: ??_R3exception@std@@8 in Debug\mymath.obj +CHECKIDX: ??_R3invalid_argument@std@@8 in Debug\mymath.obj +CHECKIDX: ??_R3logic_error@std@@8 in Debug\mymath.obj +CHECKIDX: ??_R4invalid_argument@std@@6B@ in Debug\mymath.obj +CHECKIDX: ??_R4logic_error@std@@6B@ in Debug\mymath.obj +CHECKIDX: ?Add@MyMathFuncs@MathFuncs@@SANNN@Z in Debug\mymath.obj +CHECKIDX: ?Divide@MyMathFuncs@MathFuncs@@SANNN@Z in Debug\mymath.obj +CHECKIDX: ?Multiply@MyMathFuncs@MathFuncs@@SANNN@Z in Debug\mymath.obj +CHECKIDX: ?Subtract@MyMathFuncs@MathFuncs@@SANNN@Z in Debug\mymath.obj +CHECKIDX: ?_Rank@?$_Arithmetic_traits@C@std@@2HB in Debug\mymath.obj +CHECKIDX: ?_Rank@?$_Arithmetic_traits@D@std@@2HB in Debug\mymath.obj +CHECKIDX: ?_Rank@?$_Arithmetic_traits@E@std@@2HB in Debug\mymath.obj +CHECKIDX: ?_Rank@?$_Arithmetic_traits@F@std@@2HB in Debug\mymath.obj +CHECKIDX: ?_Rank@?$_Arithmetic_traits@G@std@@2HB in Debug\mymath.obj +CHECKIDX: ?_Rank@?$_Arithmetic_traits@H@std@@2HB in Debug\mymath.obj +CHECKIDX: ?_Rank@?$_Arithmetic_traits@I@std@@2HB in Debug\mymath.obj +CHECKIDX: ?_Rank@?$_Arithmetic_traits@J@std@@2HB in Debug\mymath.obj +CHECKIDX: ?_Rank@?$_Arithmetic_traits@K@std@@2HB in Debug\mymath.obj +CHECKIDX: ?_Rank@?$_Arithmetic_traits@M@std@@2HB in Debug\mymath.obj +CHECKIDX: ?_Rank@?$_Arithmetic_traits@N@std@@2HB in Debug\mymath.obj +CHECKIDX: ?_Rank@?$_Arithmetic_traits@O@std@@2HB in Debug\mymath.obj +CHECKIDX: ?_Rank@?$_Arithmetic_traits@_J@std@@2HB in Debug\mymath.obj +CHECKIDX: ?_Rank@?$_Arithmetic_traits@_K@std@@2HB in Debug\mymath.obj +CHECKIDX: ?_Rank@?$_Arithmetic_traits@_N@std@@2HB in Debug\mymath.obj +CHECKIDX: ?value@?$integral_constant@I$0A@@tr1@std@@2IB in Debug\mymath.obj +CHECKIDX: ?value@?$integral_constant@_N$00@tr1@std@@2_NB in Debug\mymath.obj +CHECKIDX: ?value@?$integral_constant@_N$0A@@tr1@std@@2_NB in Debug\mymath.obj +CHECKIDX: __CT??_R0PAVexception@std@@@84 in Debug\mymath.obj +CHECKIDX: __CT??_R0PAVinvalid_argument@std@@@84 in Debug\mymath.obj +CHECKIDX: __CT??_R0PAVlogic_error@std@@@84 in Debug\mymath.obj +CHECKIDX: __CT??_R0PAX@84 in Debug\mymath.obj +CHECKIDX: __CTA4PAVinvalid_argument@std@@ in Debug\mymath.obj +CHECKIDX: __TI4PAVinvalid_argument@std@@ in Debug\mymath.obj +CHECKIDX: __real@0000000000000000 in Debug\mymath.obj +CHECKIDX: Debug\stdafx.obj: +CHECKIDX: 00000000 N .debug$S +CHECKIDX: 00000000 N .debug$T +CHECKIDX: 00000000 i .drectve +CHECKIDX: 00ab9d1b a @comp.id +CHECKIDX: 00000001 a @feat.00 +CHECKIDX: Debug\mymath.obj: +CHECKIDX: 00000000 d .data +CHECKIDX: 00000000 d .data +CHECKIDX: 00000000 d .data +CHECKIDX: 00000000 d .data +CHECKIDX: 00000000 d .data +CHECKIDX: 00000000 d .data +CHECKIDX: 00000000 d .data +CHECKIDX: 00000000 N .debug$S +CHECKIDX: 00000000 N .debug$S +CHECKIDX: 00000000 N .debug$S +CHECKIDX: 00000000 N .debug$S +CHECKIDX: 00000000 N .debug$S +CHECKIDX: 00000000 N .debug$S +CHECKIDX: 00000000 N .debug$S +CHECKIDX: 00000000 N .debug$S +CHECKIDX: 00000000 N .debug$S +CHECKIDX: 00000000 N .debug$S +CHECKIDX: 00000000 N .debug$S +CHECKIDX: 00000000 N .debug$T +CHECKIDX: 00000000 i .drectve +CHECKIDX: 00000000 r .rdata +CHECKIDX: 00000000 r .rdata +CHECKIDX: 00000000 r .rdata +CHECKIDX: 00000000 r .rdata +CHECKIDX: 00000000 r .rdata +CHECKIDX: 00000000 r .rdata +CHECKIDX: 00000000 r .rdata +CHECKIDX: 00000000 r .rdata +CHECKIDX: 00000000 r .rdata +CHECKIDX: 00000000 r .rdata +CHECKIDX: 00000000 r .rdata +CHECKIDX: 00000000 r .rdata +CHECKIDX: 00000000 r .rdata +CHECKIDX: 00000000 r .rdata +CHECKIDX: 00000000 r .rdata +CHECKIDX: 00000000 r .rdata +CHECKIDX: 00000000 r .rdata +CHECKIDX: 00000000 r .rdata +CHECKIDX: 00000000 r .rdata +CHECKIDX: 00000000 r .rdata +CHECKIDX: 00000000 r .rdata +CHECKIDX: 00000000 r .rdata +CHECKIDX: 00000000 r .rdata$r +CHECKIDX: 00000000 r .rdata$r +CHECKIDX: 00000000 r .rdata$r +CHECKIDX: 00000000 r .rdata$r +CHECKIDX: 00000000 r .rdata$r +CHECKIDX: 00000000 r .rdata$r +CHECKIDX: 00000000 r .rdata$r +CHECKIDX: 00000000 r .rdata$r +CHECKIDX: 00000000 r .rdata$r +CHECKIDX: 00000000 r .rdata$r +CHECKIDX: 00000000 r .rdata$r +CHECKIDX: 00000000 r .rtc$IMZ +CHECKIDX: 00000000 r .rtc$TMZ +CHECKIDX: 00000000 N .sxdata +CHECKIDX: 00000000 t .text +CHECKIDX: 00000000 t .text +CHECKIDX: 00000000 t .text +CHECKIDX: 00000000 t .text +CHECKIDX: 00000000 t .text +CHECKIDX: 00000000 t .text +CHECKIDX: 00000000 t .text +CHECKIDX: 00000000 t .text +CHECKIDX: 00000000 t .text +CHECKIDX: 00000000 t .text +CHECKIDX: 00000000 t .text$x +CHECKIDX: 00000000 r .xdata$x +CHECKIDX: 00000000 r .xdata$x +CHECKIDX: 00000000 r .xdata$x +CHECKIDX: 00000000 r .xdata$x +CHECKIDX: 00000000 r .xdata$x +CHECKIDX: 00000000 r .xdata$x +CHECKIDX: 00000000 r .xdata$x +CHECKIDX: 00000000 T ??0invalid_argument@std@@QAE@PBD@Z +CHECKIDX: 00000000 T ??0logic_error@std@@QAE@PBD@Z +CHECKIDX: 00000000 T ??1invalid_argument@std@@UAE@XZ +CHECKIDX: 00000000 T ??1logic_error@std@@UAE@XZ +CHECKIDX: U ??2@YAPAXI@Z +CHECKIDX: U ??3@YAXPAX@Z +CHECKIDX: 00000004 R ??_7invalid_argument@std@@6B@ +CHECKIDX: 00000004 R ??_7logic_error@std@@6B@ +CHECKIDX: U ??_7type_info@@6B@ +CHECKIDX: 00000000 R ??_C@_0BC@IHENMCGI@b?5cannot?5be?5zero?$CB?$AA@ +CHECKIDX: w ??_Einvalid_argument@std@@UAEPAXI@Z +CHECKIDX: w ??_Elogic_error@std@@UAEPAXI@Z +CHECKIDX: U ??_Ginvalid_argument@std@@UAEPAXI@Z +CHECKIDX: 00000000 T ??_Ginvalid_argument@std@@UAEPAXI@Z +CHECKIDX: 00000000 T ??_Glogic_error@std@@UAEPAXI@Z +CHECKIDX: U ??_Glogic_error@std@@UAEPAXI@Z +CHECKIDX: 00000000 D ??_R0?AVexception@std@@@8 +CHECKIDX: 00000000 D ??_R0?AVinvalid_argument@std@@@8 +CHECKIDX: 00000000 D ??_R0?AVlogic_error@std@@@8 +CHECKIDX: 00000000 D ??_R0PAVexception@std@@@8 +CHECKIDX: 00000000 D ??_R0PAVinvalid_argument@std@@@8 +CHECKIDX: 00000000 D ??_R0PAVlogic_error@std@@@8 +CHECKIDX: 00000000 D ??_R0PAX@8 +CHECKIDX: 00000000 R ??_R1A@?0A@EA@exception@std@@8 +CHECKIDX: 00000000 R ??_R1A@?0A@EA@invalid_argument@std@@8 +CHECKIDX: 00000000 R ??_R1A@?0A@EA@logic_error@std@@8 +CHECKIDX: 00000000 R ??_R2exception@std@@8 +CHECKIDX: 00000000 R ??_R2invalid_argument@std@@8 +CHECKIDX: 00000000 R ??_R2logic_error@std@@8 +CHECKIDX: 00000000 R ??_R3exception@std@@8 +CHECKIDX: 00000000 R ??_R3invalid_argument@std@@8 +CHECKIDX: 00000000 R ??_R3logic_error@std@@8 +CHECKIDX: 00000000 R ??_R4invalid_argument@std@@6B@ +CHECKIDX: 00000000 R ??_R4logic_error@std@@6B@ +CHECKIDX: 00000000 T ?Add@MyMathFuncs@MathFuncs@@SANNN@Z +CHECKIDX: 00000000 T ?Divide@MyMathFuncs@MathFuncs@@SANNN@Z +CHECKIDX: 00000000 T ?Multiply@MyMathFuncs@MathFuncs@@SANNN@Z +CHECKIDX: 00000000 T ?Subtract@MyMathFuncs@MathFuncs@@SANNN@Z +CHECKIDX: 00000000 R ?_Rank@?$_Arithmetic_traits@C@std@@2HB +CHECKIDX: 00000000 R ?_Rank@?$_Arithmetic_traits@D@std@@2HB +CHECKIDX: 00000000 R ?_Rank@?$_Arithmetic_traits@E@std@@2HB +CHECKIDX: 00000000 R ?_Rank@?$_Arithmetic_traits@F@std@@2HB +CHECKIDX: 00000000 R ?_Rank@?$_Arithmetic_traits@G@std@@2HB +CHECKIDX: 00000000 R ?_Rank@?$_Arithmetic_traits@H@std@@2HB +CHECKIDX: 00000000 R ?_Rank@?$_Arithmetic_traits@I@std@@2HB +CHECKIDX: 00000000 R ?_Rank@?$_Arithmetic_traits@J@std@@2HB +CHECKIDX: 00000000 R ?_Rank@?$_Arithmetic_traits@K@std@@2HB +CHECKIDX: 00000000 R ?_Rank@?$_Arithmetic_traits@M@std@@2HB +CHECKIDX: 00000000 R ?_Rank@?$_Arithmetic_traits@N@std@@2HB +CHECKIDX: 00000000 R ?_Rank@?$_Arithmetic_traits@O@std@@2HB +CHECKIDX: 00000000 R ?_Rank@?$_Arithmetic_traits@_J@std@@2HB +CHECKIDX: 00000000 R ?_Rank@?$_Arithmetic_traits@_K@std@@2HB +CHECKIDX: 00000000 R ?_Rank@?$_Arithmetic_traits@_N@std@@2HB +CHECKIDX: 00000000 R ?value@?$integral_constant@I$0A@@tr1@std@@2IB +CHECKIDX: 00000000 R ?value@?$integral_constant@_N$00@tr1@std@@2_NB +CHECKIDX: 00000000 R ?value@?$integral_constant@_N$0A@@tr1@std@@2_NB +CHECKIDX: U ?what@exception@std@@UBEPBDXZ +CHECKIDX: U @__security_check_cookie@4 +CHECKIDX: 00ab9d1b a @comp.id +CHECKIDX: 00000001 a @feat.00 +CHECKIDX: 00000000 R __CT??_R0PAVexception@std@@@84 +CHECKIDX: 00000000 R __CT??_R0PAVinvalid_argument@std@@@84 +CHECKIDX: 00000000 R __CT??_R0PAVlogic_error@std@@@84 +CHECKIDX: 00000000 R __CT??_R0PAX@84 +CHECKIDX: 00000000 R __CTA4PAVinvalid_argument@std@@ +CHECKIDX: U __CxxThrowException@8 +CHECKIDX: U __RTC_CheckEsp +CHECKIDX: U __RTC_InitBase +CHECKIDX: 00000000 r __RTC_InitBase.rtc$IMZ +CHECKIDX: U __RTC_Shutdown +CHECKIDX: 00000000 r __RTC_Shutdown.rtc$TMZ +CHECKIDX: 00000000 R __TI4PAVinvalid_argument@std@@ +CHECKIDX: U ___CxxFrameHandler3 +CHECKIDX: U ___security_cookie +CHECKIDX: 00000008 r __ehfuncinfo$?Divide@MyMathFuncs@MathFuncs@@SANNN@Z +CHECKIDX: 0000000e t __ehhandler$?Divide@MyMathFuncs@MathFuncs@@SANNN@Z +CHECKIDX: U __fltused +CHECKIDX: U __imp_??0exception@std@@QAE@ABQBD@Z +CHECKIDX: U __imp_??1exception@std@@UAE@XZ +CHECKIDX: 00000000 R __real@0000000000000000 +CHECKIDX: 00000000 t __unwindfunclet$?Divide@MyMathFuncs@MathFuncs@@SANNN@Z$0 +CHECKIDX: 00000000 r __unwindtable$?Divide@MyMathFuncs@MathFuncs@@SANNN@Z diff --git a/test/Object/simple-archive.test b/test/Object/simple-archive.test new file mode 100644 index 00000000000..c313f3facd9 --- /dev/null +++ b/test/Object/simple-archive.test @@ -0,0 +1,12 @@ +# +# Check if the index is appearing properly in the output file +# +RUN: llvm-nm -s %p/Inputs/libsimple_archive.a | FileCheck -check-prefix=CHECKIDX %s + +CHECKIDX: Archive map +CHECKIDX: abcdefghijklmnopqrstuvwxyz12345678 in 1.o +CHECKIDX: main in 1.o +CHECKIDX: 1.o: +CHECKIDX: 00000000 D abcdefghijklmnopqrstuvwxyz12345678 +CHECKIDX: U fn1 +CHECKIDX: 00000000 T main diff --git a/tools/llvm-nm/llvm-nm.cpp b/tools/llvm-nm/llvm-nm.cpp index 0543e83f9cb..153de952935 100644 --- a/tools/llvm-nm/llvm-nm.cpp +++ b/tools/llvm-nm/llvm-nm.cpp @@ -113,6 +113,10 @@ namespace { cl::opt WithoutAliases("without-aliases", cl::Hidden, cl::desc("Exclude aliases from output")); + cl::opt ArchiveMap("print-armap", + cl::desc("Print the archive map")); + cl::alias ArchiveMaps("s", cl::desc("Alias for --print-armap"), + cl::aliasopt(ArchiveMap)); bool PrintAddress = true; bool MultipleFiles = false; @@ -346,6 +350,24 @@ static void DumpSymbolNamesFromFile(std::string &Filename) { return; if (object::Archive *a = dyn_cast(arch.get())) { + if (ArchiveMap) { + outs() << "Archive map" << "\n"; + for (object::Archive::symbol_iterator i = a->begin_symbols(), + e = a->end_symbols(); i != e; ++i) { + object::Archive::child_iterator c; + StringRef symname; + StringRef filename; + if (error(i->getMember(c))) + return; + if (error(i->getName(symname))) + return; + if (error(c->getName(filename))) + return; + outs() << symname << " in " << filename << "\n"; + } + outs() << "\n"; + } + for (object::Archive::child_iterator i = a->begin_children(), e = a->end_children(); i != e; ++i) { OwningPtr child;