[llvm] r229520 - [Object] Support reading 64-bit MIPS ELF archives
Simon Atanasyan
simon at atanasyan.com
Tue Feb 17 10:54:22 PST 2015
Author: atanasyan
Date: Tue Feb 17 12:54:22 2015
New Revision: 229520
URL: http://llvm.org/viewvc/llvm-project?rev=229520&view=rev
Log:
[Object] Support reading 64-bit MIPS ELF archives
The 64-bit MIPS ELF archive file format is used by MIPS64 targets.
The main difference from a regular archive file is the symbol table format:
1. ar_name is equal to "/SYM64/"
2. number of symbols and offsets are 64-bit integers
http://techpubs.sgi.com/library/manuals/4000/007-4658-001/pdf/007-4658-001.pdf
Page 96
The patch allows reading of such archive files by llvm-nm, llvm-objdump
and other tools. But it does not support archive files with number of symbols
and/or offsets exceed 2^32. I think it is a rather rare case requires more
significant modification of `Archive` class code.
http://reviews.llvm.org/D7546
Added:
llvm/trunk/test/Object/Inputs/archive-test.a-irix6-mips64el
llvm/trunk/test/Object/nm-irix6.test
Modified:
llvm/trunk/include/llvm/Object/Archive.h
llvm/trunk/lib/Object/Archive.cpp
Modified: llvm/trunk/include/llvm/Object/Archive.h
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/Object/Archive.h?rev=229520&r1=229519&r2=229520&view=diff
==============================================================================
--- llvm/trunk/include/llvm/Object/Archive.h (original)
+++ llvm/trunk/include/llvm/Object/Archive.h Tue Feb 17 12:54:22 2015
@@ -178,6 +178,7 @@ public:
enum Kind {
K_GNU,
+ K_MIPS64,
K_BSD,
K_COFF
};
Modified: llvm/trunk/lib/Object/Archive.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Object/Archive.cpp?rev=229520&r1=229519&r2=229520&view=diff
==============================================================================
--- llvm/trunk/lib/Object/Archive.cpp (original)
+++ llvm/trunk/lib/Object/Archive.cpp Tue Feb 17 12:54:22 2015
@@ -162,7 +162,7 @@ ErrorOr<StringRef> Archive::Child::getNa
return object_error::parse_failed;
// GNU long file names end with a /.
- if (Parent->kind() == K_GNU) {
+ if (Parent->kind() == K_GNU || Parent->kind() == K_MIPS64) {
StringRef::size_type End = StringRef(addr).find('/');
return StringRef(addr, End);
}
@@ -273,8 +273,16 @@ Archive::Archive(MemoryBufferRef Source,
return;
}
- if (Name == "/") {
+ // MIPS 64-bit ELF archives use a special format of a symbol table.
+ // This format is marked by `ar_name` field equals to "/SYM64/".
+ // For detailed description see page 96 in the following document:
+ // http://techpubs.sgi.com/library/manuals/4000/007-4658-001/pdf/007-4658-001.pdf
+
+ bool has64SymTable = false;
+ if (Name == "/" || Name == "/SYM64/") {
SymbolTable = i;
+ if (Name == "/SYM64/")
+ has64SymTable = true;
++i;
if (i == e) {
@@ -285,7 +293,7 @@ Archive::Archive(MemoryBufferRef Source,
}
if (Name == "//") {
- Format = K_GNU;
+ Format = has64SymTable ? K_MIPS64 : K_GNU;
StringTable = i;
++i;
FirstRegular = i;
@@ -294,7 +302,7 @@ Archive::Archive(MemoryBufferRef Source,
}
if (Name[0] != '/') {
- Format = K_GNU;
+ Format = has64SymTable ? K_MIPS64 : K_GNU;
FirstRegular = i;
ec = object_error::success;
return;
@@ -348,11 +356,18 @@ StringRef Archive::Symbol::getName() con
ErrorOr<Archive::child_iterator> Archive::Symbol::getMember() const {
const char *Buf = Parent->SymbolTable->getBuffer().begin();
- const char *Offsets = Buf + 4;
+ const char *Offsets = Buf;
+ if (Parent->kind() == K_MIPS64)
+ Offsets += sizeof(uint64_t);
+ else
+ Offsets += sizeof(uint32_t);
uint32_t Offset = 0;
if (Parent->kind() == K_GNU) {
Offset =
*(reinterpret_cast<const support::ubig32_t *>(Offsets) + SymbolIndex);
+ } else if (Parent->kind() == K_MIPS64) {
+ Offset =
+ *(reinterpret_cast<const support::ubig64_t *>(Offsets) + SymbolIndex);
} else if (Parent->kind() == K_BSD) {
// The SymbolIndex is an index into the ranlib structs that start at
// Offsets (the first uint32_t is the number of bytes of the ranlib
@@ -449,6 +464,9 @@ Archive::symbol_iterator Archive::symbol
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_MIPS64) {
+ uint64_t symbol_count = *reinterpret_cast<const support::ubig64_t *>(buf);
+ buf += sizeof(uint64_t) + (symbol_count * (sizeof(uint64_t)));
} else if (kind() == K_BSD) {
// The __.SYMDEF or "__.SYMDEF SORTED" member starts with a uint32_t
// which is the number of bytes of ranlib structs that follow. The ranlib
@@ -486,6 +504,8 @@ Archive::symbol_iterator Archive::symbol
uint32_t symbol_count = 0;
if (kind() == K_GNU) {
symbol_count = *reinterpret_cast<const support::ubig32_t*>(buf);
+ } else if (kind() == K_MIPS64) {
+ symbol_count = *reinterpret_cast<const support::ubig64_t*>(buf);
} else if (kind() == K_BSD) {
symbol_count = (*reinterpret_cast<const support::ulittle32_t *>(buf)) /
(sizeof(uint32_t) * 2);
Added: llvm/trunk/test/Object/Inputs/archive-test.a-irix6-mips64el
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Object/Inputs/archive-test.a-irix6-mips64el?rev=229520&view=auto
==============================================================================
Binary files llvm/trunk/test/Object/Inputs/archive-test.a-irix6-mips64el (added) and llvm/trunk/test/Object/Inputs/archive-test.a-irix6-mips64el Tue Feb 17 12:54:22 2015 differ
Added: llvm/trunk/test/Object/nm-irix6.test
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Object/nm-irix6.test?rev=229520&view=auto
==============================================================================
--- llvm/trunk/test/Object/nm-irix6.test (added)
+++ llvm/trunk/test/Object/nm-irix6.test Tue Feb 17 12:54:22 2015
@@ -0,0 +1,27 @@
+# Check reading IRIX 6.0 64-bit archive file.
+RUN: llvm-nm %p/Inputs/archive-test.a-irix6-mips64el | FileCheck %s
+
+CHECK: f1.o:
+CHECK-NEXT: 00000028 T f1
+CHECK-NEXT: 00000000 d s_d
+CHECK-NEXT: 00000000 t s_foo
+
+CHECK: f2.o:
+CHECK-NEXT: 00000028 T f2
+CHECK-NEXT: 00000000 d s_d
+CHECK-NEXT: 00000000 t s_foo
+
+CHECK: f3.o:
+CHECK-NEXT: 00000028 T f3
+CHECK-NEXT: 00000000 d s_d
+CHECK-NEXT: 00000000 t s_foo
+
+CHECK: f4.o:
+CHECK-NEXT: 00000028 T f4
+CHECK-NEXT: 00000000 d s_d
+CHECK-NEXT: 00000000 t s_foo
+
+CHECK: f5.o:
+CHECK-NEXT: 00000028 T f5
+CHECK-NEXT: 00000000 d s_d
+CHECK-NEXT: 00000000 t s_foo
More information about the llvm-commits
mailing list