[llvm-commits] [lld] Supporting archive libraries in lld
Michael Spencer
bigcheesegs at gmail.com
Tue Nov 6 14:51:42 PST 2012
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
More information about the llvm-commits
mailing list