Skip to content

Commit

Permalink
[AIX] support xcoff for llvm-nm
Browse files Browse the repository at this point in the history
Summary:

add the xcoff symbol type functionality for llvm-nm.

Reviewers: James Henderson
Differential Revision: https://reviews.llvm.org/D112450
  • Loading branch information
diggerlin committed Jan 11, 2022
1 parent a81b0c9 commit 6bf20aa
Show file tree
Hide file tree
Showing 4 changed files with 214 additions and 0 deletions.
118 changes: 118 additions & 0 deletions llvm/test/tools/llvm-nm/XCOFF/basic.test
@@ -0,0 +1,118 @@
## Test llvm-nm for XCOFF object files.

# RUN: yaml2obj %s -o %t.o
# RUN: llvm-nm %t.o | FileCheck --match-full-lines %s

--- !XCOFF
FileHeader:
MagicNumber: 0x1DF
Sections:
- Name: .text
Address: 0x0
Flags: [ STYP_TEXT ]
- Name: .data
Flags: [ STYP_DATA ]
- Name: .bss
Flags: [ STYP_BSS ]
- Name: .debug
Flags: [ STYP_DEBUG ]
- Name: .except
Flags: [ STYP_EXCEPT ]
Symbols:
- Name: .file
Section: N_DEBUG
StorageClass: C_FILE
- Name: .text
Value: 0x10
Section: .text
StorageClass: C_STAT
NumberOfAuxEntries: 1
- Name: .data
Value: 0x80
Section: .data
StorageClass: C_STAT
NumberOfAuxEntries: 1
- Name: .bss
Value: 0x310
Section: .bss
StorageClass: C_STAT
- Name: .debug
Section: .debug
StorageClass: C_STAT
- Name: ._ZL5func0v
Section: .text
StorageClass: C_EXT
Type: 0x20
AuxEntries:
- Type: AUX_CSECT
SymbolAlignmentAndType: 0x02
StorageMappingClass: XMC_PR
- Name: ._Z3fwpv
Section: .text
StorageClass: C_WEAKEXT
Type: 0x20
AuxEntries:
- Type: AUX_CSECT
SymbolAlignmentAndType: 0x02
StorageMappingClass: XMC_PR
- Name: val
Section: .data
StorageClass: C_EXT
Type: 0x20
AuxEntries:
- Type: AUX_CSECT
SymbolAlignmentAndType: 0x01
StorageMappingClass: XMC_RW
SectionOrLength: 0x4
- Name: extval
Section: N_UNDEF
StorageClass: C_EXT
Type: 0x00
AuxEntries:
- Type: AUX_CSECT
SymbolAlignmentAndType: 0x01
StorageMappingClass: XMC_UA
SectionOrLength: 0x0
- Name: comval
Section: .bss
Value: 0x13C
StorageClass: C_EXT
Type: 0x00
AuxEntries:
- Type: AUX_CSECT
SymbolAlignmentAndType: 0x03
StorageMappingClass: XMC_RW
SectionOrLength: 0x0
- Name: abs
Section: N_ABS
- Name: symIn_N_debug
Section: N_DEBUG
- Name: .except
Section: .except

## Global weak symbol.
# CHECK: 00000000 W ._Z3fwpv
## Global symbol in .text section.
# CHECK-NEXT: 00000000 T ._ZL5func0v
## Symbol in .bss section.
# CHECK-NEXT: 00000310 b .bss
## Local symbol in .data section.
# CHECK-NEXT: 00000080 d .data
## Symbol in .debug section.
# CHECK-NEXT: 00000000 N .debug
## Symbol in .except section.
# CHECK-NEXT: 00000000 ? .except
## Symbol .file.
# CHECK-NEXT: 00000000 f .file
## Local symbol in .text section.
# CHECK-NEXT: 00000010 t .text
## Absolute symbol.
# CHECK-NEXT: 00000000 a abs
## Common symbol.
# CHECK-NEXT: 0000013c C comval
## Undefined symbol.
# CHECK-NEXT: U extval
## Symbol in N_DEBUG section.
# CHECK-NEXT: 00000000 ? symIn_N_debug
## Global symbol in .data section.
# CHECK-NEXT: 00000000 D val
20 changes: 20 additions & 0 deletions llvm/test/tools/llvm-nm/XCOFF/basic_64.test
@@ -0,0 +1,20 @@
## Test showing 8 byte addresses for llvm-nm for XCOFF 64-bit object files.

# RUN: yaml2obj %s -o %t.o
# RUN: llvm-nm %t.o | FileCheck --match-full-lines %s

--- !XCOFF
FileHeader:
MagicNumber: 0x1F7
Sections:
- Name: .text
Address: 0x0
Flags: [ STYP_TEXT ]
Symbols:
- Name: .text
Value: 0x10
Section: .text
StorageClass: C_STAT
NumberOfAuxEntries: 1

# CHECK: 0000000000000010 t .text
20 changes: 20 additions & 0 deletions llvm/test/tools/llvm-nm/XCOFF/invalid-section-index.test
@@ -0,0 +1,20 @@
## Test the behavior of the symbol reference section.

# RUN: yaml2obj %s -o %t.o
# RUN: llvm-nm %t.o 2>&1 | FileCheck %s -DFILE=%t.o

# CHECK: llvm-nm{{(\.exe)?}}: warning: [[FILE]]: for symbol with index 0: the section index (4) is invalid
# CHECK-NEXT: 00000000 ? .text

--- !XCOFF
FileHeader:
MagicNumber: 0x1DF
Sections:
- Name: .text
Symbols:
- Name: .text
Value: 0x0
SectionIndex: 4
Type: 0x0
StorageClass: C_STAT
NumberOfAuxEntries: 1
56 changes: 56 additions & 0 deletions llvm/tools/llvm-nm/llvm-nm.cpp
Expand Up @@ -31,6 +31,7 @@
#include "llvm/Object/TapiFile.h"
#include "llvm/Object/TapiUniversal.h"
#include "llvm/Object/Wasm.h"
#include "llvm/Object/XCOFFObjectFile.h"
#include "llvm/Option/Arg.h"
#include "llvm/Option/ArgList.h"
#include "llvm/Option/Option.h"
Expand Down Expand Up @@ -127,6 +128,20 @@ static bool HadError = false;

static StringRef ToolName;

static void warn(Error Err, Twine FileName, Twine Context = Twine()) {
assert(Err);

// Flush the standard output so that the warning isn't interleaved with other
// output if stdout and stderr are writing to the same place.
outs().flush();

handleAllErrors(std::move(Err), [&](const ErrorInfoBase &EI) {
WithColor::warning(errs(), ToolName)
<< FileName << ": " << (Context.str().empty() ? "" : Context + ": ")
<< EI.message() << "\n";
});
}

static void error(Twine Message, Twine Path = Twine()) {
HadError = true;
WithColor::error(errs(), ToolName) << Path << ": " << Message << "\n";
Expand Down Expand Up @@ -246,6 +261,9 @@ static char isSymbolList64Bit(SymbolicFile &Obj) {
return Triple(IRObj->getTargetTriple()).isArch64Bit();
if (isa<COFFObjectFile>(Obj) || isa<COFFImportFile>(Obj))
return false;
if (XCOFFObjectFile *XCOFFObj = dyn_cast<XCOFFObjectFile>(&Obj))
return XCOFFObj->is64Bit();

if (isa<WasmObjectFile>(Obj))
return false;
if (TapiFile *Tapi = dyn_cast<TapiFile>(&Obj))
Expand Down Expand Up @@ -897,6 +915,42 @@ static char getSymbolNMTypeChar(COFFObjectFile &Obj, symbol_iterator I) {
return '?';
}

static char getSymbolNMTypeChar(XCOFFObjectFile &Obj, symbol_iterator I) {
Expected<uint32_t> TypeOrErr = I->getType();
if (!TypeOrErr) {
warn(TypeOrErr.takeError(), Obj.getFileName(),
"for symbol with index " +
Twine(Obj.getSymbolIndex(I->getRawDataRefImpl().p)));
return '?';
}

uint32_t SymType = *TypeOrErr;

if (SymType == SymbolRef::ST_File)
return 'f';

// If the I->getSection() call would return an error, the earlier I->getType()
// call will already have returned the same error first.
section_iterator SecIter = cantFail(I->getSection());

if (SecIter == Obj.section_end())
return '?';

if (Obj.isDebugSection(SecIter->getRawDataRefImpl()))
return 'N';

if (SecIter->isText())
return 't';

if (SecIter->isData())
return 'd';

if (SecIter->isBSS())
return 'b';

return '?';
}

static char getSymbolNMTypeChar(COFFImportFile &Obj) {
switch (Obj.getCOFFImportHeader()->getType()) {
case COFF::IMPORT_CODE:
Expand Down Expand Up @@ -1045,6 +1099,8 @@ static char getNMSectionTagAndName(SymbolicFile &Obj, basic_symbol_iterator I,
Ret = getSymbolNMTypeChar(*IR, I);
else if (COFFObjectFile *COFF = dyn_cast<COFFObjectFile>(&Obj))
Ret = getSymbolNMTypeChar(*COFF, I);
else if (XCOFFObjectFile *XCOFF = dyn_cast<XCOFFObjectFile>(&Obj))
Ret = getSymbolNMTypeChar(*XCOFF, I);
else if (COFFImportFile *COFFImport = dyn_cast<COFFImportFile>(&Obj))
Ret = getSymbolNMTypeChar(*COFFImport);
else if (MachOObjectFile *MachO = dyn_cast<MachOObjectFile>(&Obj))
Expand Down

0 comments on commit 6bf20aa

Please sign in to comment.