-
Notifications
You must be signed in to change notification settings - Fork 15.4k
[llvm-symbolizer] Recognize AIX big archive #150401
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Changes from 13 commits
d98ed02
64639e1
f5a357e
305ef99
66d5d11
27b4f10
647f98e
629e7a5
8c71818
f0be9a8
bfa845e
9c14b38
f8aeb3e
0952fcf
6be8d1a
12dd6e5
68b886f
d0f0a1d
fe5a9c2
e2083eb
12bf16a
0595460
4d46767
315b98c
b37409b
30e4387
08f38ae
ca85990
844906c
74d4e23
183197a
c68b4d9
7407769
4da5ebd
b0f0705
86f2023
f034d90
c6d8b90
e4d6fed
f57d66a
c3acb24
136bde7
b59b5f7
8a2a05d
59f4b64
93e5a7c
af06657
b12e445
307fb74
d91dcd8
181ee67
fdcfdc0
2ad39b3
d16b8d4
0b06059
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -535,16 +535,20 @@ MACH-O SPECIFIC OPTIONS | |
| .. option:: --default-arch <arch> | ||
|
|
||
| If a binary contains object files for multiple architectures (e.g. it is a | ||
| Mach-O universal binary), symbolize the object file for a given architecture. | ||
| You can also specify the architecture by writing ``binary_name:arch_name`` in | ||
| the input (see example below). If the architecture is not specified in either | ||
| way, the address will not be symbolized. Defaults to empty string. | ||
| Mach-O universal binary or an AIX archive with architecture variants), | ||
| symbolize the object file for a given architecture. You can also specify | ||
| the architecture by writing ``binary_name:arch_name`` in the input (see | ||
| example below). For AIX archives, the format ``archive.a(member.o):arch`` | ||
|
Collaborator
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. The docs here still refer to AIX archives specifically, yet the behaviour change is generic.
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Shared objects are normally stored in (and loaded from) archives on AIX. By convention, the same (big format) archive contains both 32-bit and 64-bit objects This behaviour is AIX specific, hence the documentation is more specific to AIX
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Behavior such as having same object name which vary in architecture getting added to archive is specific to AIX |
||
| is also supported. If the architecture is not specified in either way, | ||
jh7370 marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
|
||
| the address will not be symbolized. Defaults to empty string. | ||
|
|
||
| .. code-block:: console | ||
|
|
||
| $ cat addr.txt | ||
| /tmp/mach_universal_binary:i386 0x1f84 | ||
| /tmp/mach_universal_binary:x86_64 0x100000f24 | ||
| /tmp/big-archive.a(member.o):ppc 0x1000 | ||
| /tmp/big-archive.a(member.o):ppc64 0x2000 | ||
|
|
||
| $ llvm-symbolizer < addr.txt | ||
| _main | ||
|
|
@@ -553,6 +557,12 @@ MACH-O SPECIFIC OPTIONS | |
| _main | ||
| /tmp/source_x86_64.cc:8 | ||
|
|
||
| _foo | ||
| /tmp/source_ppc.cc:12 | ||
|
|
||
| _foo | ||
| /tmp/source_ppc64.cc:12 | ||
|
|
||
| .. option:: --dsym-hint <path/to/file.dSYM> | ||
|
|
||
| If the debug info for a binary isn't present in the default location, look for | ||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -21,6 +21,7 @@ | |
| #include "llvm/DebugInfo/PDB/PDBContext.h" | ||
| #include "llvm/DebugInfo/Symbolize/SymbolizableObjectFile.h" | ||
| #include "llvm/Demangle/Demangle.h" | ||
| #include "llvm/Object/Archive.h" | ||
| #include "llvm/Object/BuildID.h" | ||
| #include "llvm/Object/COFF.h" | ||
| #include "llvm/Object/ELFObjectFile.h" | ||
|
|
@@ -286,6 +287,7 @@ LLVMSymbolizer::findSymbol(ArrayRef<uint8_t> BuildID, StringRef Symbol, | |
|
|
||
| void LLVMSymbolizer::flush() { | ||
| ObjectForUBPathAndArch.clear(); | ||
| ObjectForArchivePathAndArch.clear(); | ||
| LRUBinaries.clear(); | ||
| CacheSize = 0; | ||
| BinaryForPath.clear(); | ||
|
|
@@ -557,19 +559,103 @@ LLVMSymbolizer::getOrCreateObjectPair(const std::string &Path, | |
| if (!DbgObj) | ||
| DbgObj = Obj; | ||
| ObjectPair Res = std::make_pair(Obj, DbgObj); | ||
| std::string DbgObjPath = DbgObj->getFileName().str(); | ||
| auto Pair = | ||
| ObjectPairForPathArch.emplace(std::make_pair(Path, ArchName), Res); | ||
| BinaryForPath.find(DbgObjPath)->second.pushEvictor([this, I = Pair.first]() { | ||
| ObjectPairForPathArch.erase(I); | ||
| }); | ||
| std::string DbgObjPath = DbgObj->getFileName().str(); | ||
| auto BinIter = BinaryForPath.find(DbgObjPath); | ||
| if (BinIter != BinaryForPath.end()) { | ||
|
||
| BinIter->second.pushEvictor( | ||
| [this, I = Pair.first]() { ObjectPairForPathArch.erase(I); }); | ||
| } | ||
| return Res; | ||
| } | ||
|
|
||
| Expected<ObjectFile *> LLVMSymbolizer::getOrCreateObjectFromArchive( | ||
jh7370 marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
|
||
| StringRef ArchivePath, StringRef MemberName, StringRef ArchName) { | ||
| Binary *Bin = nullptr; | ||
| auto Pair = BinaryForPath.emplace(ArchivePath.str(), OwningBinary<Binary>()); | ||
| if (!Pair.second) { | ||
| Bin = Pair.first->second->getBinary(); | ||
| recordAccess(Pair.first->second); | ||
| } else { | ||
| Expected<OwningBinary<Binary>> ArchiveOrErr = createBinary(ArchivePath); | ||
| if (!ArchiveOrErr) | ||
| return ArchiveOrErr.takeError(); | ||
|
|
||
| CachedBinary &CachedBin = Pair.first->second; | ||
| CachedBin = std::move(ArchiveOrErr.get()); | ||
| CachedBin.pushEvictor([this, I = Pair.first]() { BinaryForPath.erase(I); }); | ||
| LRUBinaries.push_back(CachedBin); | ||
| CacheSize += CachedBin.size(); | ||
| Bin = CachedBin->getBinary(); | ||
| } | ||
|
|
||
| object::Archive *Archive = dyn_cast_if_present<object::Archive>(Bin); | ||
| if (!Archive) | ||
| return errorCodeToError(object_error::invalid_file_type); | ||
jh7370 marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
|
||
|
|
||
| Error Err = Error::success(); | ||
|
|
||
| // On AIX, archives can contain multiple members with same name but different | ||
jh7370 marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
|
||
| // types. We need to check all matches and find one that matches both name and | ||
| // architecture. | ||
| for (auto &Child : Archive->children(Err, /*SkipInternal=*/true)) { | ||
| Expected<StringRef> NameOrErr = Child.getName(); | ||
| if (!NameOrErr) | ||
| continue; | ||
jh7370 marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
|
||
| if (*NameOrErr == sys::path::filename(MemberName)) { | ||
|
||
| Expected<std::unique_ptr<object::Binary>> MemberOrErr = | ||
| Child.getAsBinary(); | ||
| if (!MemberOrErr) | ||
| continue; | ||
jh7370 marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
|
||
|
|
||
| std::unique_ptr<object::Binary> Binary = std::move(*MemberOrErr); | ||
| if (auto *Obj = dyn_cast<object::ObjectFile>(Binary.get())) { | ||
| Triple::ArchType ObjArch = Obj->makeTriple().getArch(); | ||
| Triple RequestedTriple; | ||
| RequestedTriple.setArch(Triple::getArchTypeForLLVMName(ArchName)); | ||
| if (ObjArch != RequestedTriple.getArch()) | ||
| continue; | ||
| ArchiveCacheKey CacheKey{ArchivePath.str(), MemberName.str(), | ||
| ArchName.str()}; | ||
| auto I = ObjectForArchivePathAndArch.find(CacheKey); | ||
| if (I != ObjectForArchivePathAndArch.end()) | ||
| return I->second.get(); | ||
|
|
||
| auto CachedObj = std::unique_ptr<ObjectFile>(Obj); | ||
| auto NewEntry = | ||
| ObjectForArchivePathAndArch.emplace(CacheKey, std::move(CachedObj)); | ||
| Binary.release(); | ||
| BinaryForPath.find(ArchivePath.str()) | ||
| ->second.pushEvictor([this, Iter = NewEntry.first]() { | ||
| ObjectForArchivePathAndArch.erase(Iter); | ||
| }); | ||
| return NewEntry.first->second.get(); | ||
| } | ||
| } | ||
| } | ||
| if (Err) | ||
| return std::move(Err); | ||
| return errorCodeToError(object_error::arch_not_found); | ||
| } | ||
|
|
||
| Expected<ObjectFile *> | ||
| LLVMSymbolizer::getOrCreateObject(const std::string &Path, | ||
| const std::string &ArchName) { | ||
| Binary *Bin; | ||
| // First check for archive(member) format - more efficient to check closing | ||
| // paren first. | ||
| size_t CloseParen = Path.rfind(')'); | ||
| if (CloseParen != std::string::npos && CloseParen == Path.length() - 1) { | ||
|
||
| size_t OpenParen = Path.rfind('(', CloseParen); | ||
| if (OpenParen != std::string::npos) { | ||
| StringRef ArchivePath = StringRef(Path).substr(0, OpenParen); | ||
| StringRef MemberName = | ||
| StringRef(Path).substr(OpenParen + 1, CloseParen - OpenParen - 1); | ||
jh7370 marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
|
||
| return getOrCreateObjectFromArchive(ArchivePath, MemberName, ArchName); | ||
| } | ||
| } | ||
|
|
||
| Binary *Bin = nullptr; | ||
| auto Pair = BinaryForPath.emplace(Path, OwningBinary<Binary>()); | ||
| if (!Pair.second) { | ||
| Bin = Pair.first->second->getBinary(); | ||
|
|
@@ -648,7 +734,9 @@ LLVMSymbolizer::getOrCreateModuleInfo(StringRef ModuleName) { | |
|
|
||
| auto I = Modules.find(ModuleName); | ||
| if (I != Modules.end()) { | ||
| recordAccess(BinaryForPath.find(BinaryName)->second); | ||
| auto BinIter = BinaryForPath.find(BinaryName); | ||
| if (BinIter != BinaryForPath.end()) | ||
|
||
| recordAccess(BinIter->second); | ||
| return I->second.get(); | ||
| } | ||
|
|
||
|
|
@@ -716,9 +804,9 @@ LLVMSymbolizer::getOrCreateModuleInfo(StringRef ModuleName) { | |
| createModuleInfo(Objects.first, std::move(Context), ModuleName); | ||
| if (ModuleOrErr) { | ||
| auto I = Modules.find(ModuleName); | ||
| BinaryForPath.find(BinaryName)->second.pushEvictor([this, I]() { | ||
| Modules.erase(I); | ||
| }); | ||
| auto BinIter = BinaryForPath.find(BinaryName); | ||
| if (BinIter != BinaryForPath.end()) | ||
|
||
| BinIter->second.pushEvictor([this, I]() { Modules.erase(I); }); | ||
| } | ||
| return ModuleOrErr; | ||
| } | ||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,119 @@ | ||
| --- !XCOFF | ||
|
Collaborator
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Naming the file "big-archive" doesn't make sense, because the output file is an XCOFF file, not an archive file. Just call it xcoff-32.yaml or similar. Do we really need so much bloat in the file? The idea of YAML inputs is generally to have small, focused inputs where we can easily see what's relevant to the test. From what I can tell, all you need to have is the minimal file header info, one symbol, and a section for that symbol to be in (and even the section is potentially unnecessary). If we can minimise the size, it would then make more sense to put the files inline in the test, rather than separate, to keep everything related to a test together. |
||
| FileHeader: | ||
| MagicNumber: 0x1DF | ||
| NumberOfSections: 2 | ||
| CreationTime: 0 | ||
| OffsetToSymbolTable: 0xA0 | ||
| EntriesInSymbolTable: 11 | ||
| AuxiliaryHeaderSize: 0 | ||
| Flags: 0x0 | ||
| Sections: | ||
| - Name: .text | ||
| Address: 0x0 | ||
| Size: 0x1C | ||
| FileOffsetToData: 0x64 | ||
| FileOffsetToRelocations: 0x0 | ||
| FileOffsetToLineNumbers: 0x0 | ||
| NumberOfRelocations: 0x0 | ||
| NumberOfLineNumbers: 0x0 | ||
| Flags: [ STYP_TEXT ] | ||
| SectionData: 4E800020000000000009204000000001000000040003666F6F000000 | ||
| - Name: .data | ||
| Address: 0x1C | ||
| Size: 0xC | ||
| FileOffsetToData: 0x80 | ||
| FileOffsetToRelocations: 0x8C | ||
| FileOffsetToLineNumbers: 0x0 | ||
| NumberOfRelocations: 0x2 | ||
| NumberOfLineNumbers: 0x0 | ||
| Flags: [ STYP_DATA ] | ||
| SectionData: '000000000000002800000000' | ||
| Relocations: | ||
| - Address: 0x1C | ||
| Symbol: 0x5 | ||
| Info: 0x1F | ||
| Type: 0x0 | ||
| - Address: 0x20 | ||
| Symbol: 0x9 | ||
| Info: 0x1F | ||
| Type: 0x0 | ||
| Symbols: | ||
| - Name: .file | ||
| Value: 0x0 | ||
| Section: N_DEBUG | ||
| Type: 0x18 | ||
| StorageClass: C_FILE | ||
| NumberOfAuxEntries: 2 | ||
| AuxEntries: | ||
| - Type: AUX_FILE | ||
| FileNameOrString: foo.c | ||
| FileStringType: XFT_FN | ||
| - Type: AUX_FILE | ||
| FileNameOrString: 'IBM Open XL C/C++ for AIX 17.1.3 (5725-C72, 5765-J18), version 17.1.3.0, LLVM version 21.0.0git (145c02cece3630765e6412e6820bc446ddb4e138)' | ||
| FileStringType: XFT_CV | ||
| - Name: '' | ||
| Value: 0x0 | ||
| Section: .text | ||
| Type: 0x0 | ||
| StorageClass: C_HIDEXT | ||
| NumberOfAuxEntries: 1 | ||
| AuxEntries: | ||
| - Type: AUX_CSECT | ||
| ParameterHashIndex: 0 | ||
| TypeChkSectNum: 0 | ||
| SymbolType: XTY_SD | ||
| SymbolAlignment: 5 | ||
| StorageMappingClass: XMC_PR | ||
| SectionOrLength: 25 | ||
| StabInfoIndex: 0 | ||
| StabSectNum: 0 | ||
| - Name: .foo | ||
| Value: 0x0 | ||
| Section: .text | ||
| Type: 0x0 | ||
| StorageClass: C_EXT | ||
| NumberOfAuxEntries: 1 | ||
| AuxEntries: | ||
| - Type: AUX_CSECT | ||
| ParameterHashIndex: 0 | ||
| TypeChkSectNum: 0 | ||
| SymbolType: XTY_LD | ||
| SymbolAlignment: 0 | ||
| StorageMappingClass: XMC_PR | ||
| SectionOrLength: 3 | ||
| StabInfoIndex: 0 | ||
| StabSectNum: 0 | ||
| - Name: foo | ||
| Value: 0x1C | ||
| Section: .data | ||
| Type: 0x0 | ||
| StorageClass: C_EXT | ||
| NumberOfAuxEntries: 1 | ||
| AuxEntries: | ||
| - Type: AUX_CSECT | ||
| ParameterHashIndex: 0 | ||
| TypeChkSectNum: 0 | ||
| SymbolType: XTY_SD | ||
| SymbolAlignment: 2 | ||
| StorageMappingClass: XMC_DS | ||
| SectionOrLength: 12 | ||
| StabInfoIndex: 0 | ||
| StabSectNum: 0 | ||
| - Name: TOC | ||
| Value: 0x28 | ||
| Section: .data | ||
| Type: 0x0 | ||
| StorageClass: C_HIDEXT | ||
| NumberOfAuxEntries: 1 | ||
| AuxEntries: | ||
| - Type: AUX_CSECT | ||
| ParameterHashIndex: 0 | ||
| TypeChkSectNum: 0 | ||
| SymbolType: XTY_SD | ||
| SymbolAlignment: 2 | ||
| StorageMappingClass: XMC_TC0 | ||
| SectionOrLength: 0 | ||
| StabInfoIndex: 0 | ||
| StabSectNum: 0 | ||
| StringTable: {} | ||
| ... | ||
Uh oh!
There was an error while loading. Please reload this page.