summaryrefslogtreecommitdiffstats
path: root/tools
diff options
context:
space:
mode:
authorRafael Espindola <rafael.espindola@gmail.com>2013-11-02 21:16:09 +0000
committerRafael Espindola <rafael.espindola@gmail.com>2013-11-02 21:16:09 +0000
commitbc884fd9f7bdb64d250be639edc8dc85a20a1975 (patch)
tree7ca35c37e582f10e30efc71b734ba0712a079557 /tools
parent66b8ec520f84c704e2a7f89dfa9ee1452ef5bc43 (diff)
downloadexternal_llvm-bc884fd9f7bdb64d250be639edc8dc85a20a1975.zip
external_llvm-bc884fd9f7bdb64d250be639edc8dc85a20a1975.tar.gz
external_llvm-bc884fd9f7bdb64d250be639edc8dc85a20a1975.tar.bz2
move getSymbolNMTypeChar to the one program that needs it: nm.
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@193933 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'tools')
-rw-r--r--tools/llvm-nm/llvm-nm.cpp225
1 files changed, 224 insertions, 1 deletions
diff --git a/tools/llvm-nm/llvm-nm.cpp b/tools/llvm-nm/llvm-nm.cpp
index 01dd1c3..8449c29 100644
--- a/tools/llvm-nm/llvm-nm.cpp
+++ b/tools/llvm-nm/llvm-nm.cpp
@@ -20,6 +20,9 @@
#include "llvm/Bitcode/ReaderWriter.h"
#include "llvm/IR/Module.h"
#include "llvm/Object/Archive.h"
+#include "llvm/Object/COFF.h"
+#include "llvm/Object/ELFObjectFile.h"
+#include "llvm/Object/MachO.h"
#include "llvm/Object/MachOUniversal.h"
#include "llvm/Object/ObjectFile.h"
#include "llvm/Support/CommandLine.h"
@@ -303,6 +306,226 @@ static void DumpSymbolNamesFromModule(Module *M) {
SortAndPrintSymbolList();
}
+template <class ELFT>
+error_code getSymbolNMTypeChar(ELFObjectFile<ELFT> &Obj, symbol_iterator I,
+ char &Result) {
+ typedef typename ELFObjectFile<ELFT>::Elf_Sym Elf_Sym;
+ typedef typename ELFObjectFile<ELFT>::Elf_Shdr Elf_Shdr;
+
+ DataRefImpl Symb = I->getRawDataRefImpl();
+ const Elf_Sym *ESym = Obj.getSymbol(Symb);
+ const ELFFile<ELFT> &EF = *Obj.getELFFile();
+ const Elf_Shdr *ESec = EF.getSection(ESym);
+
+ char ret = '?';
+
+ if (ESec) {
+ switch (ESec->sh_type) {
+ case ELF::SHT_PROGBITS:
+ case ELF::SHT_DYNAMIC:
+ switch (ESec->sh_flags) {
+ case(ELF::SHF_ALLOC | ELF::SHF_EXECINSTR) :
+ ret = 't';
+ break;
+ case(ELF::SHF_ALLOC | ELF::SHF_WRITE) :
+ ret = 'd';
+ break;
+ case ELF::SHF_ALLOC:
+ case(ELF::SHF_ALLOC | ELF::SHF_MERGE) :
+ case(ELF::SHF_ALLOC | ELF::SHF_MERGE | ELF::SHF_STRINGS) :
+ ret = 'r';
+ break;
+ }
+ break;
+ case ELF::SHT_NOBITS:
+ ret = 'b';
+ }
+ }
+
+ switch (EF.getSymbolTableIndex(ESym)) {
+ case ELF::SHN_UNDEF:
+ if (ret == '?')
+ ret = 'U';
+ break;
+ case ELF::SHN_ABS:
+ ret = 'a';
+ break;
+ case ELF::SHN_COMMON:
+ ret = 'c';
+ break;
+ }
+
+ switch (ESym->getBinding()) {
+ case ELF::STB_GLOBAL:
+ ret = ::toupper(ret);
+ break;
+ case ELF::STB_WEAK:
+ if (EF.getSymbolTableIndex(ESym) == ELF::SHN_UNDEF)
+ ret = 'w';
+ else if (ESym->getType() == ELF::STT_OBJECT)
+ ret = 'V';
+ else
+ ret = 'W';
+ }
+
+ if (ret == '?' && ESym->getType() == ELF::STT_SECTION) {
+ StringRef Name;
+ error_code EC = I->getName(Name);
+ if (EC)
+ return EC;
+ Result = StringSwitch<char>(Name)
+ .StartsWith(".debug", 'N')
+ .StartsWith(".note", 'n')
+ .Default('?');
+ return object_error::success;
+ }
+
+ Result = ret;
+ return object_error::success;
+}
+
+static error_code getSymbolNMTypeChar(COFFObjectFile &Obj, symbol_iterator I,
+ char &Result) {
+ const coff_symbol *symb = Obj.getCOFFSymbol(I);
+ StringRef name;
+ if (error_code ec = I->getName(name))
+ return ec;
+ char ret = StringSwitch<char>(name)
+ .StartsWith(".debug", 'N')
+ .StartsWith(".sxdata", 'N')
+ .Default('?');
+
+ if (ret != '?') {
+ Result = ret;
+ return object_error::success;
+ }
+
+ uint32_t Characteristics = 0;
+ if (symb->SectionNumber > 0) {
+ section_iterator SecI = Obj.end_sections();
+ if (error_code ec = I->getSection(SecI))
+ return ec;
+ const coff_section *Section = Obj.getCOFFSection(SecI);
+ Characteristics = Section->Characteristics;
+ }
+
+ switch (symb->SectionNumber) {
+ case COFF::IMAGE_SYM_UNDEFINED:
+ // Check storage classes.
+ if (symb->StorageClass == COFF::IMAGE_SYM_CLASS_WEAK_EXTERNAL) {
+ Result = 'w';
+ return object_error::success; // Don't do ::toupper.
+ } else if (symb->Value != 0) // Check for common symbols.
+ ret = 'c';
+ else
+ ret = 'u';
+ break;
+ case COFF::IMAGE_SYM_ABSOLUTE:
+ ret = 'a';
+ break;
+ case COFF::IMAGE_SYM_DEBUG:
+ ret = 'n';
+ break;
+ default:
+ // Check section type.
+ if (Characteristics & COFF::IMAGE_SCN_CNT_CODE)
+ ret = 't';
+ else if (Characteristics & COFF::IMAGE_SCN_MEM_READ &&
+ ~Characteristics & COFF::IMAGE_SCN_MEM_WRITE) // Read only.
+ ret = 'r';
+ else if (Characteristics & COFF::IMAGE_SCN_CNT_INITIALIZED_DATA)
+ ret = 'd';
+ else if (Characteristics & COFF::IMAGE_SCN_CNT_UNINITIALIZED_DATA)
+ ret = 'b';
+ else if (Characteristics & COFF::IMAGE_SCN_LNK_INFO)
+ ret = 'i';
+
+ // Check for section symbol.
+ else if (symb->StorageClass == COFF::IMAGE_SYM_CLASS_STATIC &&
+ symb->Value == 0)
+ ret = 's';
+ }
+
+ if (symb->StorageClass == COFF::IMAGE_SYM_CLASS_EXTERNAL)
+ ret = ::toupper(static_cast<unsigned char>(ret));
+
+ Result = ret;
+ return object_error::success;
+}
+
+static uint8_t getNType(MachOObjectFile &Obj, DataRefImpl Symb) {
+ if (Obj.is64Bit()) {
+ MachO::nlist_64 STE = Obj.getSymbol64TableEntry(Symb);
+ return STE.n_type;
+ }
+ MachO::nlist STE = Obj.getSymbolTableEntry(Symb);
+ return STE.n_type;
+}
+
+static error_code getSymbolNMTypeChar(MachOObjectFile &Obj, symbol_iterator I,
+ char &Res) {
+ DataRefImpl Symb = I->getRawDataRefImpl();
+ uint8_t NType = getNType(Obj, Symb);
+
+ char Char;
+ switch (NType & MachO::N_TYPE) {
+ case MachO::N_UNDF:
+ Char = 'u';
+ break;
+ case MachO::N_ABS:
+ Char = 's';
+ break;
+ case MachO::N_SECT: {
+ section_iterator Sec = Obj.end_sections();
+ Obj.getSymbolSection(Symb, Sec);
+ DataRefImpl Ref = Sec->getRawDataRefImpl();
+ StringRef SectionName;
+ Obj.getSectionName(Ref, SectionName);
+ StringRef SegmentName = Obj.getSectionFinalSegmentName(Ref);
+ if (SegmentName == "__TEXT" && SectionName == "__text")
+ Char = 't';
+ else
+ Char = 's';
+ } break;
+ default:
+ Char = '?';
+ break;
+ }
+
+ if (NType & (MachO::N_EXT | MachO::N_PEXT))
+ Char = toupper(static_cast<unsigned char>(Char));
+ Res = Char;
+ return object_error::success;
+}
+
+static char getNMTypeChar(ObjectFile *Obj, symbol_iterator I) {
+ char Res = '?';
+ if (COFFObjectFile *COFF = dyn_cast<COFFObjectFile>(Obj)) {
+ error(getSymbolNMTypeChar(*COFF, I, Res));
+ return Res;
+ }
+ if (MachOObjectFile *MachO = dyn_cast<MachOObjectFile>(Obj)) {
+ error(getSymbolNMTypeChar(*MachO, I, Res));
+ return Res;
+ }
+
+ if (ELF32LEObjectFile *ELF = dyn_cast<ELF32LEObjectFile>(Obj)) {
+ error(getSymbolNMTypeChar(*ELF, I, Res));
+ return Res;
+ }
+ if (ELF64LEObjectFile *ELF = dyn_cast<ELF64LEObjectFile>(Obj)) {
+ error(getSymbolNMTypeChar(*ELF, I, Res));
+ return Res;
+ }
+ if (ELF32BEObjectFile *ELF = dyn_cast<ELF32BEObjectFile>(Obj)) {
+ error(getSymbolNMTypeChar(*ELF, I, Res));
+ return Res;
+ }
+ ELF64BEObjectFile *ELF = cast<ELF64BEObjectFile>(Obj);
+ error(getSymbolNMTypeChar(*ELF, I, Res));
+ return Res;
+}
+
static void DumpSymbolNamesFromObject(ObjectFile *obj) {
error_code ec;
symbol_iterator ibegin = obj->begin_symbols();
@@ -325,7 +548,7 @@ static void DumpSymbolNamesFromObject(ObjectFile *obj) {
}
if (PrintAddress)
if (error(i->getAddress(s.Address))) break;
- if (error(i->getNMTypeChar(s.TypeChar))) break;
+ s.TypeChar = getNMTypeChar(obj, i);
if (error(i->getName(s.Name))) break;
SymbolList.push_back(s);
}