RUN: | FileCheck %s -check-prefix macho-j
RUN: llvm-nm -r %p/Inputs/macho-text-data-bss.macho-x86_64 \
RUN: | FileCheck %s -check-prefix macho-r
+RUN: llvm-nm %p/Inputs/macho-text-data-bss.macho-x86_64 -s __DATA __data \
+RUN: | FileCheck %s -check-prefix macho-s
RUN: llvm-nm %p/Inputs/common.coff-i386 \
RUN: | FileCheck %s -check-prefix COFF-COMMON
RUN: llvm-nm %p/Inputs/relocatable-with-section-address.elf-x86-64 \
macho-r-NEXT: 0000000000000070 b _b
macho-r-NEXT: 0000000000000030 s EH_frame0
+macho-s: 000000000000000c D _d
+macho-s-NOT: 0000000000000048 S _t.eh
+macho-s-NOT: 0000000000000000 T _t
+macho-s-NOT: 0000000000000070 b _b
+macho-s-NOT: 0000000000000030 s EH_frame0
+
Test that nm uses addresses even with ELF .o files.
ELF-SEC-ADDR64: 0000000000000058 D a
ELF-SEC-ADDR64-NEXT: 000000000000005c D b
cl::desc("Print just the symbol's name"));
cl::alias JustSymbolNames("j", cl::desc("Alias for --just-symbol-name"),
cl::aliasopt(JustSymbolName));
+
+// FIXME: This option takes exactly two strings and should be allowed anywhere
+// on the command line. Such that "llvm-nm -s __TEXT __text foo.o" would work.
+// But that does not as the CommandLine Library does not have a way to make
+// this work. For now the "-s __TEXT __text" has to be last on the command
+// line.
+cl::list<std::string> SegSect("s", cl::Positional, cl::ZeroOrMore,
+ cl::desc("Dump only symbols from this segment "
+ "and section name, Mach-O only"));
+
bool PrintAddress = true;
bool MultipleFiles = false;
return Ret;
}
+// getNsectForSegSect() is used to implement the Mach-O "-s segname sectname"
+// option to dump only those symbols from that section in a Mach-O file.
+// It is called once for each Mach-O file from dumpSymbolNamesFromObject()
+// to get the section number for that named section from the command line
+// arguments. It returns the section number for that section in the Mach-O
+// file or zero it is not present.
+static unsigned getNsectForSegSect(MachOObjectFile *Obj) {
+ unsigned Nsect = 1;
+ for (section_iterator I = Obj->section_begin(), E = Obj->section_end();
+ I != E; ++I) {
+ DataRefImpl Ref = I->getRawDataRefImpl();
+ StringRef SectionName;
+ Obj->getSectionName(Ref, SectionName);
+ StringRef SegmentName = Obj->getSectionFinalSegmentName(Ref);
+ if (SegmentName == SegSect[0] && SectionName == SegSect[1])
+ return Nsect;
+ Nsect++;
+ }
+ return 0;
+}
+
+// getNsectInMachO() is used to implement the Mach-O "-s segname sectname"
+// option to dump only those symbols from that section in a Mach-O file.
+// It is called once for each symbol in a Mach-O file from
+// dumpSymbolNamesFromObject() and returns the section number for that symbol
+// if it is in a section, else it returns 0.
+static unsigned getNsectInMachO(MachOObjectFile &Obj, basic_symbol_iterator I) {
+ DataRefImpl Symb = I->getRawDataRefImpl();
+ if (Obj.is64Bit()) {
+ MachO::nlist_64 STE = Obj.getSymbol64TableEntry(Symb);
+ if ((STE.n_type & MachO::N_TYPE) == MachO::N_SECT)
+ return STE.n_sect;
+ return 0;
+ }
+ MachO::nlist STE = Obj.getSymbolTableEntry(Symb);
+ if ((STE.n_type & MachO::N_TYPE) == MachO::N_SECT)
+ return STE.n_sect;
+ return 0;
+}
+
static void dumpSymbolNamesFromObject(SymbolicFile *Obj, bool printName) {
basic_symbol_iterator IBegin = Obj->symbol_begin();
basic_symbol_iterator IEnd = Obj->symbol_end();
}
std::string NameBuffer;
raw_string_ostream OS(NameBuffer);
+ // If a "-s segname sectname" option was specified and this is a Mach-O
+ // file get the section number for that section in this object file.
+ unsigned int Nsect = 0;
+ MachOObjectFile *MachO = dyn_cast<MachOObjectFile>(Obj);
+ if (SegSect.size() != 0 && MachO) {
+ Nsect = getNsectForSegSect(MachO);
+ // If this section is not in the object file no symbols are printed.
+ if (Nsect == 0)
+ return;
+ }
for (basic_symbol_iterator I = IBegin; I != IEnd; ++I) {
uint32_t SymFlags = I->getFlags();
if (!DebugSyms && (SymFlags & SymbolRef::SF_FormatSpecific))
continue;
}
}
+ // If a "-s segname sectname" option was specified and this is a Mach-O
+ // file and this section appears in this file, Nsect will be non-zero then
+ // see if this symbol is a symbol from that section and if not skip it.
+ if (Nsect && Nsect != getNsectInMachO(*MachO, I))
+ continue;
NMSymbol S;
S.Size = UnknownAddressOrSize;
S.Address = UnknownAddressOrSize;
}
}
+ if (SegSect.size() != 0 && SegSect.size() != 2)
+ error("bad number of arguments (must be two arguments)",
+ "for the -s option");
+
+
std::for_each(InputFilenames.begin(), InputFilenames.end(),
dumpSymbolNamesFromFile);