[llvm-commits] [lld] Supporting archive libraries in lld

Shankar Easwaran shankare at codeaurora.org
Wed Nov 7 10:07:43 PST 2012


Hi Nick, Michael,

I have attached the complete diff after the changes you mentioned.

Note: the indentation issue earlier was caused by the diff tool earlier.

Ok to commit ?

Thanks

Shankar Easwaran

On 11/6/2012 5:10 PM, Shankar Easwaran wrote:
> Hi Michael,
>
> Thanks for the review.
>
> The indentation in the source looked fine but the diff option -uw made 
> the diff appear differently than the source.
>
> Fixed the diff output and resending the llvm diff.
>
> Thanks
>
> Shankar Easwaran
>
>
> On 11/6/2012 4:51 PM, Michael Spencer wrote:
>> On Tue, Nov 6, 2012 at 8:30 AM, Shankar Easwaran
>> <shankare at codeaurora.org> wrote:
>>> Hi Nick, Michael,
>>>
>>> I incorporated your comments in lld / llvm for supporting reading 
>>> archive
>>> libraries.
>>>
>>> Please look at the new changes and let me know if you are ok to 
>>> commit this
>>> in.
>>>
>>> Thanks
>>>
>>> Shankar Easwaran
>>>
>>> -- 
>>> Qualcomm Innovation Center, Inc. is a member of Code Aurora Forum, 
>>> hosted by
>>> the Linux Foundation
>>>
>>> Index: lib/Object/Archive.cpp
>>> ===================================================================
>>> --- lib/Object/Archive.cpp  (revision 167054)
>>> +++ lib/Object/Archive.cpp  (working copy)
>>> @@ -122,7 +122,15 @@
>>>                      + sizeof(ArchiveMemberHeader)
>>>                      + Parent->StringTable->getSize()))
>>>         return object_error::parse_failed;
>>> +
>>> +    // The filename would exist in the StringTable only if the 
>>> filename
>>> +    // is a long filename. The filename be terminated by a /
>> This should read:
>>
>> GNU long file names end with a /.
>>
>>> +    if (Parent->kind() == K_GNU) {
>>> +      StringRef::size_type end = StringRef(addr).find('/');
>> End
>>
>>> +      Result = StringRef(addr, end);
>>> +    } else {
>>>       Result = addr;
>> This needs to be indented.
>>
>>> +    }
>>>       return object_error::success;
>>>     } else if (name.startswith("#1/")) {
>>>       APInt name_size;
>>> @@ -187,7 +195,40 @@
>>>     child_iterator i = begin_children(false);
>>>     child_iterator e = end_children();
>>>
>>> -  if (i != e) ++i; // Nobody cares about the first member.
>>> +  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/<size>, The size 
>>> represents the size
>>> +  //  of the filename that needs to be read after the archive header
>>> +  //  COFF archive format
>> This should be spaced the same as GNU archive format and BSD 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;
>>> +    const char *data = name.data();
>>> +    if (data[0] != '/') {
>> You don't need to convert to a const char * to do this. name[0] is 
>> the same.
>>
>>> +      Format = K_GNU;
>>> +    } else if (data[1] == '/') {
>>> +      Format = K_GNU;
>>> +      StringTable = i;
>>> +      ++i;
>>> +    } else  {
>>> +      Format = K_COFF;
>>>     if (i != e) {
>>>       SymbolTable = i;
>>>       ++i;
>>> @@ -195,7 +236,12 @@
>>>     if (i != e) {
>>>       StringTable = i;
>>>     }
>> This needs to be indented.
>>
>>> -
>>> +    }
>>> +  } else if (name == "__.SYMDEF") {
>>> +    Format = K_BSD;
>>> +    SymbolTable = i;
>>> +    StringTable = e;
>>> +  }
>>>     ec = object_error::success;
>>>   }
>>>
>>> @@ -222,17 +268,28 @@
>>>
>>>   error_code Archive::Symbol::getMember(child_iterator &Result) const {
>>>     const char *buf = 
>>> Parent->SymbolTable->getBuffer()->getBufferStart();
>>> -  uint32_t member_count = *reinterpret_cast<const 
>>> support::ulittle32_t*>(buf);
>>>     const char *offsets = buf + 4;
>>> +  uint32_t offset = 0;
>>> +  if (Parent->kind() == K_GNU) {
>>> +    offset = *(reinterpret_cast<const support::ubig32_t*>(offsets)
>>> +                          + SymbolIndex);
>>> +  } else if (Parent->kind() == K_BSD) {
>>> +    assert("BSD format is not supported");
>>> +  } else {
>>> +    uint32_t member_count = 0;
>>> +    member_count = *reinterpret_cast<const 
>>> support::ulittle32_t*>(buf);
>>>     buf += 4 + (member_count * 4); // Skip offsets.
>>>     const char *indicies = buf + 4;
>>> -
>>>     uint16_t offsetindex =
>>>       *(reinterpret_cast<const support::ulittle16_t*>(indicies)
>>>         + SymbolIndex);
>> Indentation is wrong.
>>
>>> -
>>> -  uint32_t offset = *(reinterpret_cast<const 
>>> support::ulittle32_t*>(offsets)
>>> +    uint32_t *offsetaddr =
>>> +             (uint32_t *)(reinterpret_cast<const 
>>> support::ulittle32_t*>(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 +310,20 @@
>>>
>>>   Archive::symbol_iterator Archive::begin_symbols() const {
>>>     const char *buf = SymbolTable->getBuffer()->getBufferStart();
>>> -  uint32_t member_count = *reinterpret_cast<const 
>>> support::ulittle32_t*>(buf);
>>> +  if (kind() == K_GNU) {
>>> +    uint32_t symbol_count = 0;
>>> +    symbol_count = *reinterpret_cast<const support::ubig32_t*>(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<const 
>>> support::ulittle32_t*>(buf);
>>>     buf += 4 + (member_count * 4); // Skip offsets.
>> Indentation.
>>
>>> -  uint32_t symbol_count = *reinterpret_cast<const 
>>> support::ulittle32_t*>(buf);
>>> +    symbol_count = *reinterpret_cast<const 
>>> support::ulittle32_t*>(buf);
>>>     buf += 4 + (symbol_count * 2); // Skip indices.
>> Indentation.
>>
>>> +  }
>>>     uint32_t string_start_offset =
>>>       buf - SymbolTable->getBuffer()->getBufferStart();
>>>     return symbol_iterator(Symbol(this, 0, string_start_offset));
>>> @@ -264,9 +331,37 @@
>>>
>>>   Archive::symbol_iterator Archive::end_symbols() const {
>>>     const char *buf = SymbolTable->getBuffer()->getBufferStart();
>>> -  uint32_t member_count = *reinterpret_cast<const 
>>> support::ulittle32_t*>(buf);
>>> +  uint32_t symbol_count = 0;
>>> +  if (kind() == K_GNU) {
>>> +    symbol_count = *reinterpret_cast<const support::ubig32_t*>(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<const 
>>> support::ulittle32_t*>(buf);
>>>     buf += 4 + (member_count * 4); // Skip offsets.
>> Indentation.
>>
>>> -  uint32_t symbol_count = *reinterpret_cast<const 
>>> support::ulittle32_t*>(buf);
>>> +    symbol_count = *reinterpret_cast<const 
>>> support::ulittle32_t*>(buf);
>>> +  }
>>>     return symbol_iterator(
>>>       Symbol(this, symbol_count, 0));
>>>   }
>>> +
>>> +error_code Archive::findSym(StringRef name, child_iterator &result) 
>>> const {
>>> +  error_code ec;
>>> +  StringRef symname;
>>> +  Archive::symbol_iterator bs = begin_symbols();
>>> +  Archive::symbol_iterator es = end_symbols();
>>> +
>>> +  for (; bs != es; ++bs)
>>> +  {
>> No newline before {.
>>
>>> +    if ((ec = bs->getName(symname)))
>>> +        return ec;
>>> +    if (symname == name) {
>>> +      if ((ec = bs->getMember(result)))
>>> +        return ec;
>>> +      return error_code::success();
>>> +    }
>>> +  }
>>> +  return object_error::parse_failed;
>> This is not the right error code. parse_failed means that the file is
>> corrupt. This should return a child_iterator.
>>
>>> +}
>>>
>> - Michael Spencer
>>
>>
>
>
>
>
> _______________________________________________
> llvm-commits mailing list
> llvm-commits at cs.uiuc.edu
> http://lists.cs.uiuc.edu/mailman/listinfo/llvm-commits


-- 
Qualcomm Innovation Center, Inc. is a member of Code Aurora Forum, hosted by the Linux Foundation

-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.llvm.org/pipermail/llvm-commits/attachments/20121107/4c89cd0e/attachment.html>
-------------- next part --------------
Index: test/Object/Inputs/coff_archive.lib
===================================================================
Cannot display: file marked as a binary type.
svn:mime-type = application/octet-stream

Property changes on: test/Object/Inputs/coff_archive.lib
___________________________________________________________________
Added: svn:executable
   + *
Added: svn:mime-type
   + application/octet-stream

Index: test/Object/Inputs/liblong_filenames.a
===================================================================
Cannot display: file marked as a binary type.
svn:mime-type = application/octet-stream

Property changes on: test/Object/Inputs/liblong_filenames.a
___________________________________________________________________
Added: svn:mime-type
   + application/octet-stream

Index: test/Object/Inputs/libsimple_archive.a
===================================================================
Cannot display: file marked as a binary type.
svn:mime-type = application/octet-stream

Property changes on: test/Object/Inputs/libsimple_archive.a
___________________________________________________________________
Added: svn:mime-type
   + application/octet-stream

Index: test/Object/simple-archive.test
===================================================================
--- test/Object/simple-archive.test	(revision 0)
+++ test/Object/simple-archive.test	(revision 0)
@@ -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
Index: test/Object/archive-long-index.test
===================================================================
--- test/Object/archive-long-index.test	(revision 0)
+++ test/Object/archive-long-index.test	(revision 0)
@@ -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
Index: test/Object/coff-archive.test
===================================================================
--- test/Object/coff-archive.test	(revision 0)
+++ test/Object/coff-archive.test	(revision 0)
@@ -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 at std@@QAE at PBD@Z in Debug\mymath.obj
+CHECKIDX: ??0logic_error at std@@QAE at PBD@Z in Debug\mymath.obj
+CHECKIDX: ??1invalid_argument at std@@UAE at XZ in Debug\mymath.obj
+CHECKIDX: ??1logic_error at std@@UAE at XZ in Debug\mymath.obj
+CHECKIDX: ??_7invalid_argument at std@@6B@ in Debug\mymath.obj
+CHECKIDX: ??_7logic_error at std@@6B@ in Debug\mymath.obj
+CHECKIDX: ??_C at _0BC@IHENMCGI at b?5cannot?5be?5zero?$CB?$AA@ in Debug\mymath.obj
+CHECKIDX: ??_Ginvalid_argument at std@@UAEPAXI at Z in Debug\mymath.obj
+CHECKIDX: ??_Glogic_error at std@@UAEPAXI at Z in Debug\mymath.obj
+CHECKIDX: ??_R0?AVexception at std@@@8 in Debug\mymath.obj
+CHECKIDX: ??_R0?AVinvalid_argument at std@@@8 in Debug\mymath.obj
+CHECKIDX: ??_R0?AVlogic_error at std@@@8 in Debug\mymath.obj
+CHECKIDX: ??_R0PAVexception at std@@@8 in Debug\mymath.obj
+CHECKIDX: ??_R0PAVinvalid_argument at std@@@8 in Debug\mymath.obj
+CHECKIDX: ??_R0PAVlogic_error at std@@@8 in Debug\mymath.obj
+CHECKIDX: ??_R0PAX at 8 in Debug\mymath.obj
+CHECKIDX: ??_R1A@?0A at EA@exception at std@@8 in Debug\mymath.obj
+CHECKIDX: ??_R1A@?0A at EA@invalid_argument at std@@8 in Debug\mymath.obj
+CHECKIDX: ??_R1A@?0A at EA@logic_error at std@@8 in Debug\mymath.obj
+CHECKIDX: ??_R2exception at std@@8 in Debug\mymath.obj
+CHECKIDX: ??_R2invalid_argument at std@@8 in Debug\mymath.obj
+CHECKIDX: ??_R2logic_error at std@@8 in Debug\mymath.obj
+CHECKIDX: ??_R3exception at std@@8 in Debug\mymath.obj
+CHECKIDX: ??_R3invalid_argument at std@@8 in Debug\mymath.obj
+CHECKIDX: ??_R3logic_error at std@@8 in Debug\mymath.obj
+CHECKIDX: ??_R4invalid_argument at std@@6B@ in Debug\mymath.obj
+CHECKIDX: ??_R4logic_error at std@@6B@ in Debug\mymath.obj
+CHECKIDX: ?Add at MyMathFuncs@MathFuncs@@SANNN at Z in Debug\mymath.obj
+CHECKIDX: ?Divide at MyMathFuncs@MathFuncs@@SANNN at Z in Debug\mymath.obj
+CHECKIDX: ?Multiply at MyMathFuncs@MathFuncs@@SANNN at Z in Debug\mymath.obj
+CHECKIDX: ?Subtract at MyMathFuncs@MathFuncs@@SANNN at Z in Debug\mymath.obj
+CHECKIDX: ?_Rank@?$_Arithmetic_traits at C@std@@2HB in Debug\mymath.obj
+CHECKIDX: ?_Rank@?$_Arithmetic_traits at D@std@@2HB in Debug\mymath.obj
+CHECKIDX: ?_Rank@?$_Arithmetic_traits at E@std@@2HB in Debug\mymath.obj
+CHECKIDX: ?_Rank@?$_Arithmetic_traits at F@std@@2HB in Debug\mymath.obj
+CHECKIDX: ?_Rank@?$_Arithmetic_traits at G@std@@2HB in Debug\mymath.obj
+CHECKIDX: ?_Rank@?$_Arithmetic_traits at H@std@@2HB in Debug\mymath.obj
+CHECKIDX: ?_Rank@?$_Arithmetic_traits at I@std@@2HB in Debug\mymath.obj
+CHECKIDX: ?_Rank@?$_Arithmetic_traits at J@std@@2HB in Debug\mymath.obj
+CHECKIDX: ?_Rank@?$_Arithmetic_traits at K@std@@2HB in Debug\mymath.obj
+CHECKIDX: ?_Rank@?$_Arithmetic_traits at M@std@@2HB in Debug\mymath.obj
+CHECKIDX: ?_Rank@?$_Arithmetic_traits at N@std@@2HB in Debug\mymath.obj
+CHECKIDX: ?_Rank@?$_Arithmetic_traits at O@std@@2HB in Debug\mymath.obj
+CHECKIDX: ?_Rank@?$_Arithmetic_traits at _J@std@@2HB in Debug\mymath.obj
+CHECKIDX: ?_Rank@?$_Arithmetic_traits at _K@std@@2HB in Debug\mymath.obj
+CHECKIDX: ?_Rank@?$_Arithmetic_traits at _N@std@@2HB in Debug\mymath.obj
+CHECKIDX: ?value@?$integral_constant at I$0A@@tr1 at std@@2IB in Debug\mymath.obj
+CHECKIDX: ?value@?$integral_constant at _N$00 at tr1@std@@2_NB in Debug\mymath.obj
+CHECKIDX: ?value@?$integral_constant at _N$0A@@tr1 at std@@2_NB in Debug\mymath.obj
+CHECKIDX: __CT??_R0PAVexception at std@@@84 in Debug\mymath.obj
+CHECKIDX: __CT??_R0PAVinvalid_argument at std@@@84 in Debug\mymath.obj
+CHECKIDX: __CT??_R0PAVlogic_error at std@@@84 in Debug\mymath.obj
+CHECKIDX: __CT??_R0PAX at 84 in Debug\mymath.obj
+CHECKIDX: __CTA4PAVinvalid_argument at std@@ in Debug\mymath.obj
+CHECKIDX: __TI4PAVinvalid_argument at std@@ in Debug\mymath.obj
+CHECKIDX: __real at 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 at std@@QAE at PBD@Z
+CHECKIDX: 00000000 T ??0logic_error at std@@QAE at PBD@Z
+CHECKIDX: 00000000 T ??1invalid_argument at std@@UAE at XZ
+CHECKIDX: 00000000 T ??1logic_error at std@@UAE at XZ
+CHECKIDX:          U ??2 at YAPAXI@Z
+CHECKIDX:          U ??3 at YAXPAX@Z
+CHECKIDX: 00000004 R ??_7invalid_argument at std@@6B@
+CHECKIDX: 00000004 R ??_7logic_error at std@@6B@
+CHECKIDX:          U ??_7type_info@@6B@
+CHECKIDX: 00000000 R ??_C at _0BC@IHENMCGI at b?5cannot?5be?5zero?$CB?$AA@
+CHECKIDX:          w ??_Einvalid_argument at std@@UAEPAXI at Z
+CHECKIDX:          w ??_Elogic_error at std@@UAEPAXI at Z
+CHECKIDX:          U ??_Ginvalid_argument at std@@UAEPAXI at Z
+CHECKIDX: 00000000 T ??_Ginvalid_argument at std@@UAEPAXI at Z
+CHECKIDX: 00000000 T ??_Glogic_error at std@@UAEPAXI at Z
+CHECKIDX:          U ??_Glogic_error at std@@UAEPAXI at Z
+CHECKIDX: 00000000 D ??_R0?AVexception at std@@@8
+CHECKIDX: 00000000 D ??_R0?AVinvalid_argument at std@@@8
+CHECKIDX: 00000000 D ??_R0?AVlogic_error at std@@@8
+CHECKIDX: 00000000 D ??_R0PAVexception at std@@@8
+CHECKIDX: 00000000 D ??_R0PAVinvalid_argument at std@@@8
+CHECKIDX: 00000000 D ??_R0PAVlogic_error at std@@@8
+CHECKIDX: 00000000 D ??_R0PAX at 8
+CHECKIDX: 00000000 R ??_R1A@?0A at EA@exception at std@@8
+CHECKIDX: 00000000 R ??_R1A@?0A at EA@invalid_argument at std@@8
+CHECKIDX: 00000000 R ??_R1A@?0A at EA@logic_error at std@@8
+CHECKIDX: 00000000 R ??_R2exception at std@@8
+CHECKIDX: 00000000 R ??_R2invalid_argument at std@@8
+CHECKIDX: 00000000 R ??_R2logic_error at std@@8
+CHECKIDX: 00000000 R ??_R3exception at std@@8
+CHECKIDX: 00000000 R ??_R3invalid_argument at std@@8
+CHECKIDX: 00000000 R ??_R3logic_error at std@@8
+CHECKIDX: 00000000 R ??_R4invalid_argument at std@@6B@
+CHECKIDX: 00000000 R ??_R4logic_error at std@@6B@
+CHECKIDX: 00000000 T ?Add at MyMathFuncs@MathFuncs@@SANNN at Z
+CHECKIDX: 00000000 T ?Divide at MyMathFuncs@MathFuncs@@SANNN at Z
+CHECKIDX: 00000000 T ?Multiply at MyMathFuncs@MathFuncs@@SANNN at Z
+CHECKIDX: 00000000 T ?Subtract at MyMathFuncs@MathFuncs@@SANNN at Z
+CHECKIDX: 00000000 R ?_Rank@?$_Arithmetic_traits at C@std@@2HB
+CHECKIDX: 00000000 R ?_Rank@?$_Arithmetic_traits at D@std@@2HB
+CHECKIDX: 00000000 R ?_Rank@?$_Arithmetic_traits at E@std@@2HB
+CHECKIDX: 00000000 R ?_Rank@?$_Arithmetic_traits at F@std@@2HB
+CHECKIDX: 00000000 R ?_Rank@?$_Arithmetic_traits at G@std@@2HB
+CHECKIDX: 00000000 R ?_Rank@?$_Arithmetic_traits at H@std@@2HB
+CHECKIDX: 00000000 R ?_Rank@?$_Arithmetic_traits at I@std@@2HB
+CHECKIDX: 00000000 R ?_Rank@?$_Arithmetic_traits at J@std@@2HB
+CHECKIDX: 00000000 R ?_Rank@?$_Arithmetic_traits at K@std@@2HB
+CHECKIDX: 00000000 R ?_Rank@?$_Arithmetic_traits at M@std@@2HB
+CHECKIDX: 00000000 R ?_Rank@?$_Arithmetic_traits at N@std@@2HB
+CHECKIDX: 00000000 R ?_Rank@?$_Arithmetic_traits at O@std@@2HB
+CHECKIDX: 00000000 R ?_Rank@?$_Arithmetic_traits at _J@std@@2HB
+CHECKIDX: 00000000 R ?_Rank@?$_Arithmetic_traits at _K@std@@2HB
+CHECKIDX: 00000000 R ?_Rank@?$_Arithmetic_traits at _N@std@@2HB
+CHECKIDX: 00000000 R ?value@?$integral_constant at I$0A@@tr1 at std@@2IB
+CHECKIDX: 00000000 R ?value@?$integral_constant at _N$00 at tr1@std@@2_NB
+CHECKIDX: 00000000 R ?value@?$integral_constant at _N$0A@@tr1 at std@@2_NB
+CHECKIDX:          U ?what at exception@std@@UBEPBDXZ
+CHECKIDX:          U @__security_check_cookie at 4
+CHECKIDX: 00ab9d1b a @comp.id
+CHECKIDX: 00000001 a @feat.00
+CHECKIDX: 00000000 R __CT??_R0PAVexception at std@@@84
+CHECKIDX: 00000000 R __CT??_R0PAVinvalid_argument at std@@@84
+CHECKIDX: 00000000 R __CT??_R0PAVlogic_error at std@@@84
+CHECKIDX: 00000000 R __CT??_R0PAX at 84
+CHECKIDX: 00000000 R __CTA4PAVinvalid_argument at std@@
+CHECKIDX:          U __CxxThrowException at 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 at std@@
+CHECKIDX:          U ___CxxFrameHandler3
+CHECKIDX:          U ___security_cookie
+CHECKIDX: 00000008 r __ehfuncinfo$?Divide at MyMathFuncs@MathFuncs@@SANNN at Z
+CHECKIDX: 0000000e t __ehhandler$?Divide at MyMathFuncs@MathFuncs@@SANNN at Z
+CHECKIDX:          U __fltused
+CHECKIDX:          U __imp_??0exception at std@@QAE at ABQBD@Z
+CHECKIDX:          U __imp_??1exception at std@@UAE at XZ
+CHECKIDX: 00000000 R __real at 0000000000000000
+CHECKIDX: 00000000 t __unwindfunclet$?Divide at MyMathFuncs@MathFuncs@@SANNN at Z$0
+CHECKIDX: 00000000 r __unwindtable$?Divide at MyMathFuncs@MathFuncs@@SANNN at Z
Index: include/llvm/Object/Archive.h
===================================================================
--- include/llvm/Object/Archive.h	(revision 167054)
+++ include/llvm/Object/Archive.h	(working copy)
@@ -122,6 +122,16 @@
 
   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 @@
     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;
 };
 
 }
Index: tools/llvm-nm/llvm-nm.cpp
===================================================================
--- tools/llvm-nm/llvm-nm.cpp	(revision 167054)
+++ tools/llvm-nm/llvm-nm.cpp	(working copy)
@@ -113,6 +113,10 @@
   cl::opt<bool> WithoutAliases("without-aliases", cl::Hidden,
                                cl::desc("Exclude aliases from output"));
 
+  cl::opt<bool> 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 @@
       return;
 
     if (object::Archive *a = dyn_cast<object::Archive>(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<Binary> child;
Index: lib/Object/Archive.cpp
===================================================================
--- lib/Object/Archive.cpp	(revision 167054)
+++ lib/Object/Archive.cpp	(working copy)
@@ -122,7 +122,14 @@
                    + 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 @@
   child_iterator i = begin_children(false);
   child_iterator e = end_children();
 
-  if (i != e) ++i; // Nobody cares about the first member.
-  if (i != e) {
+  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/<size>, 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;
-    ++i;
-  }
-  if (i != e) {
-    StringTable = 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,18 +266,29 @@
 
 error_code Archive::Symbol::getMember(child_iterator &Result) const {
   const char *buf = Parent->SymbolTable->getBuffer()->getBufferStart();
-  uint32_t member_count = *reinterpret_cast<const support::ulittle32_t*>(buf);
   const char *offsets = buf + 4;
-  buf += 4 + (member_count * 4); // Skip offsets.
-  const char *indicies = buf + 4;
+  uint32_t offset = 0;
+  if (Parent->kind() == K_GNU) {
+    offset = *(reinterpret_cast<const support::ubig32_t*>(offsets) 
+                          + SymbolIndex);
+  } else if (Parent->kind() == K_BSD) {
+    assert("BSD format is not supported");
+  } else {
+    uint32_t member_count = 0;
+    member_count = *reinterpret_cast<const support::ulittle32_t*>(buf);
+    buf += 4 + (member_count * 4); // Skip offsets.
+    const char *indicies = buf + 4;
+    uint16_t offsetindex =
+      *(reinterpret_cast<const support::ulittle16_t*>(indicies)
+        + SymbolIndex);
+    uint32_t *offsetaddr = 
+             (uint32_t *)(reinterpret_cast<const support::ulittle32_t*>(offsets)
+                          + (offsetindex - 1));
+    assert((const char *)offsetaddr < 
+           Parent->SymbolTable->getBuffer()->getBufferEnd());
+    offset = *(offsetaddr);
+  }
 
-  uint16_t offsetindex =
-    *(reinterpret_cast<const support::ulittle16_t*>(indicies)
-      + SymbolIndex);
-
-  uint32_t offset = *(reinterpret_cast<const support::ulittle32_t*>(offsets)
-                      + (offsetindex - 1));
-
   const char *Loc = Parent->getData().begin() + offset;
   size_t Size = sizeof(ArchiveMemberHeader) +
     ToHeader(Loc)->getSize();
@@ -253,10 +308,20 @@
 
 Archive::symbol_iterator Archive::begin_symbols() const {
   const char *buf = SymbolTable->getBuffer()->getBufferStart();
-  uint32_t member_count = *reinterpret_cast<const support::ulittle32_t*>(buf);
-  buf += 4 + (member_count * 4); // Skip offsets.
-  uint32_t symbol_count = *reinterpret_cast<const support::ulittle32_t*>(buf);
-  buf += 4 + (symbol_count * 2); // Skip indices.
+  if (kind() == K_GNU) {
+    uint32_t symbol_count = 0;
+    symbol_count = *reinterpret_cast<const support::ubig32_t*>(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<const support::ulittle32_t*>(buf);
+    buf += 4 + (member_count * 4); // Skip offsets.
+    symbol_count = *reinterpret_cast<const support::ulittle32_t*>(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::end_symbols() const {
   const char *buf = SymbolTable->getBuffer()->getBufferStart();
-  uint32_t member_count = *reinterpret_cast<const support::ulittle32_t*>(buf);
-  buf += 4 + (member_count * 4); // Skip offsets.
-  uint32_t symbol_count = *reinterpret_cast<const support::ulittle32_t*>(buf);
+  uint32_t symbol_count = 0;
+  if (kind() == K_GNU) {
+    symbol_count = *reinterpret_cast<const support::ubig32_t*>(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<const support::ulittle32_t*>(buf);
+    buf += 4 + (member_count * 4); // Skip offsets.
+    symbol_count = *reinterpret_cast<const support::ulittle32_t*>(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();
+}
-------------- next part --------------
Index: test/elf/Inputs/libfnarchive.x86_64
===================================================================
Cannot display: file marked as a binary type.
svn:mime-type = application/octet-stream

Property changes on: test/elf/Inputs/libfnarchive.x86_64
___________________________________________________________________
Added: svn:mime-type
   + application/octet-stream

Index: test/elf/Inputs/mainobj.x86_64
===================================================================
Cannot display: file marked as a binary type.
svn:mime-type = application/octet-stream

Property changes on: test/elf/Inputs/mainobj.x86_64
___________________________________________________________________
Added: svn:mime-type
   + application/octet-stream

Index: test/elf/archive-elf-forceload.objtxt
===================================================================
--- test/elf/archive-elf-forceload.objtxt	(revision 0)
+++ test/elf/archive-elf-forceload.objtxt	(revision 0)
@@ -0,0 +1,46 @@
+# Tests the functionality of archive libraries reading 
+# and resolution 
+#
+# Tests generated using the source files below
+# main file
+# int main()
+# {
+#   fn();
+#   return 0;
+# }
+#  
+# archive file
+# int fn()
+# {
+#   return 0;
+# }
+# 
+# int fn1()
+# {
+#   return 0;
+# }
+# gcc -c main.c fn.c fn1.c
+
+RUN: lld-core -reader ELF %p/Inputs/mainobj.x86_64 %p/Inputs/libfnarchive.x86_64 -force-load | FileCheck -check-prefix FORCELOAD %s
+
+FORCELOAD:    - name:              fn1
+FORCELOAD:      scope:             global
+FORCELOAD:      type:              code
+FORCELOAD:      section-choice:    custom-required
+FORCELOAD:      section-name:      .text
+FORCELOAD:      content:           [ 55, 48, 89, E5, B8, 00, 00, 00, 00, 5D, C3 ]
+FORCELOAD:    - name:              fn
+FORCELOAD:      scope:             global
+FORCELOAD:      type:              code
+FORCELOAD:      section-choice:    custom-required
+FORCELOAD:      section-name:      .text
+FORCELOAD:      content:           [ 55, 48, 89, E5, B8, 00, 00, 00, 00, 5D, C3 ]
+FORCELOAD:    - name:              main.c
+FORCELOAD:      definition:        absolute
+FORCELOAD:      value:             0x0
+FORCELOAD:    - name:              fn1.c
+FORCELOAD:      definition:        absolute
+FORCELOAD:      value:             0x0
+FORCELOAD:    - name:              fn.c
+FORCELOAD:      definition:        absolute
+FORCELOAD:      value:             0x0
Index: test/elf/archive-elf.objtxt
===================================================================
--- test/elf/archive-elf.objtxt	(revision 0)
+++ test/elf/archive-elf.objtxt	(revision 0)
@@ -0,0 +1,37 @@
+# Tests the functionality of archive libraries reading 
+# and resolution 
+#
+# Tests generated using the source files below
+# main file
+# int main()
+# {
+#   fn();
+#   return 0;
+# }
+#  
+# archive file
+# int fn()
+# {
+#   return 0;
+# }
+# 
+# int fn1()
+# {
+#   return 0;
+# }
+# gcc -c main.c fn.c fn1.c
+
+RUN: lld-core -reader ELF %p/Inputs/mainobj.x86_64 %p/Inputs/libfnarchive.x86_64 | FileCheck -check-prefix NOFORCELOAD %s
+
+NOFORCELOAD:    - name:              fn
+NOFORCELOAD:      scope:             global
+NOFORCELOAD:      type:              code
+NOFORCELOAD:      section-choice:    custom-required
+NOFORCELOAD:      section-name:      .text
+NOFORCELOAD:      content:           [ 55, 48, 89, E5, B8, 00, 00, 00, 00, 5D, C3 ]
+NOFORCELOAD:    - name:              main.c
+NOFORCELOAD:      definition:        absolute
+NOFORCELOAD:      value:             0x0
+NOFORCELOAD:    - name:              fn.c
+NOFORCELOAD:      definition:        absolute
+NOFORCELOAD:      value:             0x0
Index: tools/lld-core/lld-core.cpp
===================================================================
--- tools/lld-core/lld-core.cpp	(revision 166441)
+++ tools/lld-core/lld-core.cpp	(working copy)
@@ -12,6 +12,7 @@
 #include "lld/Core/Pass.h"
 #include "lld/Core/Resolver.h"
 #include "lld/ReaderWriter/Reader.h"
+#include "lld/ReaderWriter/ReaderArchive.h"
 #include "lld/ReaderWriter/ReaderNative.h"
 #include "lld/ReaderWriter/ReaderYAML.h"
 #include "lld/ReaderWriter/ReaderELF.h"
@@ -76,6 +77,10 @@
           llvm::cl::desc("Any undefined symbols at end is an error"));
 
 llvm::cl::opt<bool> 
+cmdLineForceLoad("force-load", 
+          llvm::cl::desc("force load all members of the archive"));
+
+llvm::cl::opt<bool> 
 cmdLineCommonsSearchArchives("commons-search-archives", 
           llvm::cl::desc("Tentative definitions trigger archive search"));
 
@@ -214,6 +219,8 @@
   // create object to mange input files
   InputFiles inputFiles;
 
+  ReaderOptionsArchive readerOptionsArchive(cmdLineForceLoad);
+
   // read input files into in-memory File objects
 
   TestingReaderOptionsYAML  readerOptionsYAML;
@@ -231,7 +238,9 @@
       reader = createReaderPECOFF(lld::ReaderOptionsPECOFF());
       break;
     case readerELF:
-      reader = createReaderELF(lld::ReaderOptionsELF());
+      reader = createReaderELF(lld::ReaderOptionsELF(),
+                               readerOptionsArchive);
+
       break;
     default:
       reader = createReaderYAML(readerOptionsYAML);
Index: include/lld/ReaderWriter/ReaderELF.h
===================================================================
--- include/lld/ReaderWriter/ReaderELF.h	(revision 166441)
+++ include/lld/ReaderWriter/ReaderELF.h	(working copy)
@@ -11,6 +11,7 @@
 #define LLD_READERWRITER_READER_ELF_H_
 
 #include "lld/ReaderWriter/Reader.h"
+#include "lld/ReaderWriter/ReaderArchive.h"
 #include "lld/Core/LLVM.h"
 
 
@@ -56,7 +57,8 @@
 /// ReaderOptionsELF object supplied, so the objects object must not be  
 /// destroyed before the Reader object. 
 ///
-Reader* createReaderELF(const ReaderOptionsELF &options);
+Reader* createReaderELF(const ReaderOptionsELF &options, 
+                        ReaderOptionsArchive &optionsArchive);
 
 
 
Index: include/lld/ReaderWriter/ReaderArchive.h
===================================================================
--- include/lld/ReaderWriter/ReaderArchive.h	(revision 0)
+++ include/lld/ReaderWriter/ReaderArchive.h	(revision 0)
@@ -0,0 +1,79 @@
+//===- ReaderWriter/ReaderArchive.h - Archive Library Reader ------------===//
+//
+//                             The LLVM Linker
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===--------------------------------------------------------------------===//
+
+#ifndef LLD_READER_ARCHIVE_H
+#define LLD_READER_ARCHIVE_H
+
+#include "lld/Core/ArchiveLibraryFile.h"
+#include "llvm/ADT/OwningPtr.h"
+#include "llvm/ADT/StringRef.h"
+#include "llvm/Support/MemoryBuffer.h"
+#include "llvm/Support/system_error.h"
+#include "llvm/Object/Archive.h"
+#include "lld/Core/File.h"
+#include "lld/Core/LLVM.h"
+#include "lld/ReaderWriter/Reader.h"
+#include "lld/ReaderWriter/ReaderArchive.h"
+#include <memory>
+#include <bits/unique_ptr.h>
+#include <vector>
+
+namespace lld
+{
+///
+/// The ReaderOptionsArchive encapsulates the options used by the ReaderArchive.
+/// The option objects are the only way to control the behaviour of Readers.
+///
+class ReaderOptionsArchive
+{
+public:
+  ReaderOptionsArchive(bool is_force_load=false): _isForceLoad(is_force_load),
+                                                  _reader(nullptr)
+  { }
+  
+  bool isForceLoad() const {
+    return _isForceLoad;
+  }
+  
+  Reader *reader() const {
+    return _reader;
+  }
+
+  void setReader(Reader *r) {
+    _reader = r;
+  }
+  
+private:
+  bool _isForceLoad;
+  Reader *_reader;
+};
+
+// ReaderArchive is a class for reading archive libraries
+class ReaderArchive final
+{
+public:
+  ReaderArchive(ReaderOptionsArchive &options) : _options(options),
+                                                 _archive()
+  { }
+
+  // Returns a vector of Files that are contained in the archive file 
+  // pointed to by the Memorybuffer
+  virtual error_code parseFile(std::unique_ptr<llvm::MemoryBuffer> mb,
+                               std::vector<std::unique_ptr<File>> &result);
+
+  virtual ~ReaderArchive() { }
+
+private:
+  ReaderOptionsArchive &_options;
+  std::unique_ptr<llvm::object::Archive> _archive;
+};
+
+} // namespace lld
+
+#endif // LLD_READER_ARCHIVE_H
Index: include/lld/Core/FileArchive.h
===================================================================
--- include/lld/Core/FileArchive.h	(revision 0)
+++ include/lld/Core/FileArchive.h	(revision 0)
@@ -0,0 +1,145 @@
+//===- Core/FileArchive.h - Support static library -----------------------===//
+//
+//                             The LLVM Linker
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLD_CORE_FILE_ARCHIVE_FILE_H_
+#define LLD_CORE_FILE_ARCHIVE_FILE_H_
+
+#include "lld/ReaderWriter/ReaderArchive.h"
+#include "lld/Core/ArchiveLibraryFile.h"
+#include "llvm/ADT/OwningPtr.h"
+#include "llvm/ADT/StringRef.h"
+#include "llvm/Object/ObjectFile.h"
+#include "llvm/Support/MemoryBuffer.h"
+#include "llvm/Support/system_error.h"
+#include "llvm/Object/Archive.h"
+#include "lld/Core/File.h"
+#include "lld/Core/LLVM.h"
+
+namespace lld {
+
+// The FileArchive class represents an Archive Library file
+class FileArchive : public ArchiveLibraryFile {
+public:
+
+  virtual ~FileArchive() { }
+
+  /// Check if any member of the archive contains an Atom with the
+  /// specified name and return the File object for that member, or nullptr.
+  virtual const File *find(StringRef name, bool dataSymbolOnly) const {
+    error_code ec;  
+    llvm::object::Archive::child_iterator ci;
+
+    ci = _archive.get()->findSym(name);
+    if (ci == _archive->end_children()) 
+      return nullptr;
+    
+    if (dataSymbolOnly && (ec = isDataSymbol(ci->getBuffer(), name)))
+      return nullptr;
+    
+    std::vector<std::unique_ptr<File>> result;
+
+    if ((ec = _options.reader()->parseFile(std::unique_ptr<MemoryBuffer>
+                                           (ci->getBuffer()), result)))
+      return nullptr;
+
+    assert(result.size() == 1);
+
+    // give up the pointer so that this object no longer manages it
+    for (std::unique_ptr<File> &f : result) {
+      return f.release();
+    }
+
+    return nullptr;
+  }
+
+  virtual void addAtom(const Atom&) {
+    llvm_unreachable("cannot add atoms to archive files");
+  }
+
+  virtual const atom_collection<DefinedAtom> &defined() const {
+    return _definedAtoms;
+  }
+
+  virtual const atom_collection<UndefinedAtom> &undefined() const {
+    return _undefinedAtoms;
+  }
+
+  virtual const atom_collection<SharedLibraryAtom> &sharedLibrary() const {
+    return _sharedLibraryAtoms;
+  }
+
+  virtual const atom_collection<AbsoluteAtom> &absolute() const {
+    return _absoluteAtoms;
+  }
+
+protected:
+  error_code isDataSymbol(MemoryBuffer *mb, StringRef symbol) const
+  {
+    llvm::object::ObjectFile *obj = 
+                  llvm::object::ObjectFile::createObjectFile(mb);
+    error_code ec;
+    llvm::object::SymbolRef::Type symtype;
+    uint32_t symflags;
+    llvm::object::symbol_iterator ibegin = obj->begin_symbols();
+    llvm::object::symbol_iterator iend = obj->end_symbols();
+    StringRef symbolname;
+
+    for (llvm::object::symbol_iterator i = ibegin; i != iend; i.increment(ec)) {
+      if (ec) return ec;
+      
+      // Get symbol name
+      if ((ec = (i->getName(symbolname)))) return ec;
+      
+      if (symbolname != symbol) 
+          continue;
+      
+      // Get symbol flags
+      if ((ec = (i->getFlags(symflags)))) return ec;
+      
+      if (symflags <= llvm::object::SymbolRef::SF_Undefined)
+          continue;
+      
+      // Get Symbol Type
+      if ((ec = (i->getType(symtype)))) return ec;
+      
+      if (symtype == llvm::object::SymbolRef::ST_Data) {
+        return error_code::success();
+      }
+    }
+    return llvm::object::object_error::parse_failed;
+  }
+
+private:
+  llvm::MemoryBuffer *_mb;
+  std::unique_ptr<llvm::object::Archive> _archive;
+  const ReaderOptionsArchive _options;
+  atom_collection_vector<DefinedAtom>       _definedAtoms;
+  atom_collection_vector<UndefinedAtom>     _undefinedAtoms;
+  atom_collection_vector<SharedLibraryAtom> _sharedLibraryAtoms;
+  atom_collection_vector<AbsoluteAtom>      _absoluteAtoms;
+
+public:
+  /// only subclasses of ArchiveLibraryFile can be instantiated 
+  explicit FileArchive(llvm::MemoryBuffer *mb, 
+                       const ReaderOptionsArchive &options, 
+                       error_code &ec)
+                      :ArchiveLibraryFile(mb->getBufferIdentifier()),
+                       _mb(mb),
+                       _archive(nullptr),
+                       _options(options) { 
+    auto *archive_obj = new llvm::object::Archive(mb, ec);
+    if (ec) 
+      return;
+    _archive.reset(archive_obj);
+  }
+};
+
+} // namespace lld
+
+#endif // LLD_CORE_FILE_ARCHIVE_FILE_H_
Index: lib/ReaderWriter/ReaderArchive.cpp
===================================================================
--- lib/ReaderWriter/ReaderArchive.cpp	(revision 0)
+++ lib/ReaderWriter/ReaderArchive.cpp	(revision 0)
@@ -0,0 +1,43 @@
+//===- lib/ReaderWriter/ReaderArchive.cpp - Archive Library Reader--------===//
+//
+//                             The LLVM Linker
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===---------------------------------------------------------------------===//
+#include "lld/ReaderWriter/ReaderArchive.h"
+#include "lld/Core/FileArchive.h"
+
+namespace lld 
+{
+  // Returns a vector of Files that are contained in the archive file 
+  // pointed to by the MemoryBuffer
+  error_code ReaderArchive::parseFile(std::unique_ptr<llvm::MemoryBuffer> mb,
+  		std::vector<std::unique_ptr<File>> &result) {
+    error_code ec;
+    
+    if (_options.isForceLoad())
+    {
+      _archive.reset(new llvm::object::Archive(mb.release(), ec));
+      if (ec)
+        return ec;
+      
+      for (auto mf = _archive->begin_children(), 
+                me = _archive->end_children(); mf != me; ++mf)
+      {
+      	if ((ec = _options.reader()->parseFile(std::unique_ptr<MemoryBuffer>
+                                               (mf->getBuffer()), result)))
+          return ec;
+      }
+    } else {
+      std::unique_ptr<File> f;
+      f.reset(new FileArchive(mb.release(), _options, ec));
+      if (ec)
+        return ec;
+
+      result.push_back(std::move(f));
+    }
+    return llvm::error_code::success();
+  }
+}
Index: lib/ReaderWriter/ELF/ReaderELF.cpp
===================================================================
--- lib/ReaderWriter/ELF/ReaderELF.cpp	(revision 166441)
+++ lib/ReaderWriter/ELF/ReaderELF.cpp	(working copy)
@@ -12,9 +12,9 @@
 //
 //===----------------------------------------------------------------------===//
 #include "lld/ReaderWriter/ReaderELF.h"
+#include "lld/ReaderWriter/ReaderArchive.h"
 #include "lld/Core/File.h"
 #include "lld/Core/Reference.h"
-
 #include "llvm/ADT/ArrayRef.h"
 #include "llvm/ADT/SmallString.h"
 #include "llvm/ADT/StringRef.h"
@@ -30,6 +30,7 @@
 #include "llvm/Support/MemoryBuffer.h"
 #include "llvm/Support/raw_ostream.h"
 #include "llvm/Support/system_error.h"
+#include "llvm/Support/Path.h"
 
 
 #include <map>
@@ -751,43 +752,72 @@
 
 class ReaderELF: public Reader {
 public:
-  ReaderELF(const ReaderOptionsELF &) {}
+  ReaderELF(const ReaderOptionsELF &readerELFOptions,
+            ReaderOptionsArchive &readerOptionsArchive)
+         : _readerELFOptions(readerELFOptions),
+           _readerOptionsArchive(readerOptionsArchive),
+           _readerArchive(_readerOptionsArchive) { 
+    _readerOptionsArchive.setReader(this);
+  }
+
   error_code parseFile(std::unique_ptr<MemoryBuffer> mb, std::vector<
-      std::unique_ptr<File> > &result) {
+                       std::unique_ptr<File> > &result) {
+    llvm::error_code ec; 
+    std::unique_ptr<File> f;
+    std::pair<unsigned char, unsigned char> Ident;
 
-    std::pair<unsigned char, unsigned char> Ident =
-        llvm::object::getElfArchType(&*mb);
-    llvm::error_code ec;
-    //    Instantiate the correct FileELF template instance
-    //    based on the Ident pair. Once the File is created
-    //     we push the file to the vector of files already
-    //     created during parser's life.
+    llvm::sys::LLVMFileType fileType = 
+          llvm::sys::IdentifyFileType(mb->getBufferStart(),
+                                static_cast<unsigned>(mb->getBufferSize()));
+    switch (fileType) {
 
-    std::unique_ptr<File> f;
+      case llvm::sys::ELF_Relocatable_FileType:
 
-    if (Ident.first == llvm::ELF::ELFCLASS32 && Ident.second
-        == llvm::ELF::ELFDATA2LSB) {
-      f.reset(new FileELF<llvm::support::little, false>(std::move(mb), ec));
+        Ident = llvm::object::getElfArchType(&*mb);
+        //    Instantiate the correct FileELF template instance
+        //    based on the Ident pair. Once the File is created
+        //     we push the file to the vector of files already
+        //     created during parser's life.
 
-    } else if (Ident.first == llvm::ELF::ELFCLASS32 && Ident.second
-        == llvm::ELF::ELFDATA2MSB) {
-      f.reset(new FileELF<llvm::support::big, false> (std::move(mb), ec));
+        if (Ident.first == llvm::ELF::ELFCLASS32 && Ident.second
+            == llvm::ELF::ELFDATA2LSB) {
+          f.reset(new FileELF<llvm::support::little, false>(std::move(mb), ec));
 
-    } else if (Ident.first == llvm::ELF::ELFCLASS64 && Ident.second
-        == llvm::ELF::ELFDATA2MSB) {
-      f.reset(new FileELF<llvm::support::big, true> (std::move(mb), ec));
+        } else if (Ident.first == llvm::ELF::ELFCLASS32 && Ident.second
+            == llvm::ELF::ELFDATA2MSB) {
+          f.reset(new FileELF<llvm::support::big, false> (std::move(mb), ec));
 
-    } else if (Ident.first == llvm::ELF::ELFCLASS64 && Ident.second
-        == llvm::ELF::ELFDATA2LSB) {
-      f.reset(new FileELF<llvm::support::little, true> (std::move(mb), ec));
+        } else if (Ident.first == llvm::ELF::ELFCLASS64 && Ident.second
+            == llvm::ELF::ELFDATA2MSB) {
+          f.reset(new FileELF<llvm::support::big, true> (std::move(mb), ec));
+
+        } else if (Ident.first == llvm::ELF::ELFCLASS64 && Ident.second
+            == llvm::ELF::ELFDATA2LSB) {
+          f.reset(new FileELF<llvm::support::little, true> (std::move(mb), ec));
+        }
+        if (!ec)
+          result.push_back(std::move(f));
+        break;
+
+      case llvm::sys::Archive_FileType:
+        ec = _readerArchive.parseFile(std::move(mb), result);
+        break;
+
+      default:
+        llvm_unreachable("not supported format");
+        break;
     }
 
     if (ec)
       return ec;
 
-    result.push_back(std::move(f));
     return error_code::success();
   }
+
+private:
+  const ReaderOptionsELF &_readerELFOptions;
+  ReaderOptionsArchive &_readerOptionsArchive;
+  ReaderArchive _readerArchive;
 };
 
 } // namespace anonymous
@@ -800,8 +830,9 @@
 ReaderOptionsELF::~ReaderOptionsELF() {
 }
 
-Reader *createReaderELF(const ReaderOptionsELF &options) {
-  return new ReaderELF(options);
+Reader *createReaderELF(const ReaderOptionsELF &options,
+                        ReaderOptionsArchive &optionsArchive) {
+  return new ReaderELF(options, optionsArchive);
 }
 
 } // namespace LLD
Index: lib/ReaderWriter/CMakeLists.txt
===================================================================
--- lib/ReaderWriter/CMakeLists.txt	(revision 166441)
+++ lib/ReaderWriter/CMakeLists.txt	(working copy)
@@ -6,4 +6,5 @@
 add_lld_library(lldReaderWriter
   Reader.cpp
   Writer.cpp
+  ReaderArchive.cpp
   )


More information about the llvm-commits mailing list