Skip to content

Commit ac9e155

Browse files
committed
Change llvm-objdump, llvm-nm and llvm-size when reporting an object file error
when the object is in an archive to use something like libx.a(foo.o) as part of the error message. Also changed llvm-objdump and llvm-size to be like llvm-nm and ignore non-object files in archives and not produce any error message. To do this Archive::Child::getAsBinary() was changed from ErrorOr<...> to Expected<...> then that was threaded up to its users. Converting this interface to Expected<> from ErrorOr<> does involve touching a number of places. To contain the changes for now the use of errorToErrorCode() is still used in one place yet to be fully converted. Again there some were bugs in the existing code that did not deal with the old ErrorOr<> return values.  So now with Expected<> since they must be checked and the error handled, I added a TODO and a comments for those. llvm-svn: 269784
1 parent 75259bb commit ac9e155

File tree

17 files changed

+254
-63
lines changed

17 files changed

+254
-63
lines changed

llvm/include/llvm/Object/Archive.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -101,7 +101,7 @@ class Archive : public Binary {
101101

102102
ErrorOr<MemoryBufferRef> getMemoryBufferRef() const;
103103

104-
ErrorOr<std::unique_ptr<Binary>>
104+
Expected<std::unique_ptr<Binary>>
105105
getAsBinary(LLVMContext *Context = nullptr) const;
106106
};
107107

llvm/include/llvm/Object/Error.h

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -81,4 +81,34 @@ template <>
8181
struct is_error_code_enum<llvm::object::object_error> : std::true_type {};
8282
}
8383

84+
namespace llvm {
85+
namespace object {
86+
87+
// isNotObjectErrorInvalidFileType() is used when looping through the children
88+
// of an archive after calling getAsBinary() on the child and it returns an
89+
// llvm::Error. In the cases we want to loop through the children and ignore the
90+
// non-objects in the archive this is used to test the error to see if an
91+
// error() function needs to called on the llvm::Error.
92+
static inline llvm::Error isNotObjectErrorInvalidFileType(llvm::Error Err) {
93+
if (auto Err2 =
94+
handleErrors(std::move(Err),
95+
[](std::unique_ptr<ECError> M) {
96+
// Try to handle 'M'. If successful, return a success value from
97+
// the handler.
98+
if (M->convertToErrorCode() == object_error::invalid_file_type)
99+
return Error::success();
100+
101+
// We failed to handle 'M' - return it from the handler.
102+
// This value will be passed back from catchErrors and
103+
// wind up in Err2, where it will be returned from this function.
104+
return Error(std::move(M));
105+
}))
106+
return Err2;
107+
return Err;
108+
}
109+
110+
} // end namespace object.
111+
112+
} // end namespace llvm.
113+
84114
#endif

llvm/lib/ExecutionEngine/MCJIT/MCJIT.cpp

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -329,10 +329,13 @@ RuntimeDyld::SymbolInfo MCJIT::findSymbol(const std::string &Name,
329329
report_fatal_error(EC.message());
330330
if (ChildIt != A->child_end()) {
331331
// FIXME: Support nested archives?
332-
ErrorOr<std::unique_ptr<object::Binary>> ChildBinOrErr =
332+
Expected<std::unique_ptr<object::Binary>> ChildBinOrErr =
333333
(*ChildIt)->getAsBinary();
334-
if (ChildBinOrErr.getError())
334+
if (!ChildBinOrErr) {
335+
// TODO: Actually report errors helpfully.
336+
consumeError(ChildBinOrErr.takeError());
335337
continue;
338+
}
336339
std::unique_ptr<object::Binary> &ChildBin = ChildBinOrErr.get();
337340
if (ChildBin->isObject()) {
338341
std::unique_ptr<object::ObjectFile> OF(

llvm/lib/ExecutionEngine/Orc/OrcMCJITReplacement.h

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -263,10 +263,13 @@ class OrcMCJITReplacement : public ExecutionEngine {
263263
report_fatal_error(EC.message());
264264
if (ChildIt != A->child_end()) {
265265
// FIXME: Support nested archives?
266-
ErrorOr<std::unique_ptr<object::Binary>> ChildBinOrErr =
266+
Expected<std::unique_ptr<object::Binary>> ChildBinOrErr =
267267
(*ChildIt)->getAsBinary();
268-
if (ChildBinOrErr.getError())
268+
if (!ChildBinOrErr) {
269+
// TODO: Actually report errors helpfully.
270+
consumeError(ChildBinOrErr.takeError());
269271
continue;
272+
}
270273
std::unique_ptr<object::Binary> &ChildBin = ChildBinOrErr.get();
271274
if (ChildBin->isObject()) {
272275
std::vector<std::unique_ptr<object::ObjectFile>> ObjSet;

llvm/lib/Object/Archive.cpp

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -228,6 +228,11 @@ ErrorOr<StringRef> Archive::Child::getName() const {
228228
if (name.substr(3).rtrim(' ').getAsInteger(10, name_size))
229229
llvm_unreachable("Long name length is not an ingeter");
230230
return Data.substr(sizeof(ArchiveMemberHeader), name_size).rtrim('\0');
231+
} else {
232+
// It is not a long name so trim the blanks at the end of the name.
233+
if (name[name.size() - 1] != '/') {
234+
return name.rtrim(' ');
235+
}
231236
}
232237
// It's a simple name.
233238
if (name[name.size() - 1] == '/')
@@ -246,16 +251,16 @@ ErrorOr<MemoryBufferRef> Archive::Child::getMemoryBufferRef() const {
246251
return MemoryBufferRef(*Buf, Name);
247252
}
248253

249-
ErrorOr<std::unique_ptr<Binary>>
254+
Expected<std::unique_ptr<Binary>>
250255
Archive::Child::getAsBinary(LLVMContext *Context) const {
251256
ErrorOr<MemoryBufferRef> BuffOrErr = getMemoryBufferRef();
252257
if (std::error_code EC = BuffOrErr.getError())
253-
return EC;
258+
return errorCodeToError(EC);
254259

255260
auto BinaryOrErr = createBinary(BuffOrErr.get(), Context);
256261
if (BinaryOrErr)
257262
return std::move(*BinaryOrErr);
258-
return errorToErrorCode(BinaryOrErr.takeError());
263+
return BinaryOrErr.takeError();
259264
}
260265

261266
ErrorOr<std::unique_ptr<Archive>> Archive::create(MemoryBufferRef Source) {
5.41 KB
Binary file not shown.
1.06 KB
Binary file not shown.

llvm/test/Object/macho-invalid.test

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -56,6 +56,10 @@ RUN: llvm-nm -pax %p/Inputs/macho-invalid-symbol-name-past-eof 2>&1 \
5656
RUN: | FileCheck -check-prefix NAME-PAST-EOF-nm-pax %s
5757
NAME-PAST-EOF-nm-pax: 0000000000000000 64 00 0000 fe000002 bad string index
5858

59+
RUN: not llvm-objdump -t %p/Inputs/macho-bad-archive1.a 2>&1 \
60+
RUN: | FileCheck -check-prefix NAME-PAST-EOF-ARCHIVE %s
61+
NAME-PAST-EOF-ARCHIVE: macho-bad-archive1.a(macho-invalid-symbol-name-past-eof) truncated or malformed object (bad string index: 4261412866 for symbol at index 0)
62+
5963
RUN: llvm-nm %p/Inputs/macho-invalid-section-index-getSectionRawName 2>&1 \
6064
RUN: | FileCheck -check-prefix INVALID-SECTION-IDX-SYMBOL-SEC %s
6165
INVALID-SECTION-IDX-SYMBOL-SEC: 0000000100000000 S __mh_execute_header
@@ -74,3 +78,6 @@ INVALID-HEADER: The file was not recognized as a valid object file
7478

7579
RUN: not llvm-objdump -macho -private-headers %p/Inputs/macho64-invalid-incomplete-segment-load-command 2>&1 | FileCheck -check-prefix INCOMPLETE-SEGMENT-LOADC %s
7680
INCOMPLETE-SEGMENT-LOADC: truncated or malformed object (load commands extend past the end of the file)
81+
82+
RUN: not llvm-objdump -macho -private-headers %p/Inputs/macho-bad-archive2.a 2>&1 | FileCheck -check-prefix INCOMPLETE-SEGMENT-LOADC-ARCHIVE %s
83+
INCOMPLETE-SEGMENT-LOADC-ARCHIVE: macho-bad-archive2.a(macho64-invalid-incomplete-segment-load-command) truncated or malformed object (load commands extend past the end of the file)

llvm/test/Object/nm-archive.test

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -55,9 +55,10 @@ RUN: llvm-nm %p/Inputs/archive-test.a-empty
5555

5656
This archive has an unaligned member and a unknown format member.
5757
GNU AR is able to parse the unaligned member and warns about the member with
58-
the unknown format. We should probably simply warn on both. For now just check
59-
that we don't produce an error.
60-
RUN: llvm-nm %p/Inputs/corrupt-archive.a
58+
the unknown format. We should probably simply warn on both. For now we just
59+
produce an error for the unknown format.
60+
RUN: not llvm-nm %p/Inputs/corrupt-archive.a 2>&1 | FileCheck %s -check-prefix CORRUPT
61+
CORRUPT: corrupt-archive.a(trivial-object-test2.elf-x86-64) Invalid data was encountered while parsing the file
6162

6263

6364
RUN: llvm-nm %p/Inputs/thin.a | FileCheck %s -check-prefix THIN

llvm/tools/llvm-cxxdump/llvm-cxxdump.cpp

Lines changed: 10 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -485,11 +485,17 @@ static void dumpArchive(const Archive *Arc) {
485485
for (auto &ErrorOrChild : Arc->children()) {
486486
error(ErrorOrChild.getError());
487487
const Archive::Child &ArcC = *ErrorOrChild;
488-
ErrorOr<std::unique_ptr<Binary>> ChildOrErr = ArcC.getAsBinary();
489-
if (std::error_code EC = ChildOrErr.getError()) {
488+
Expected<std::unique_ptr<Binary>> ChildOrErr = ArcC.getAsBinary();
489+
if (!ChildOrErr) {
490490
// Ignore non-object files.
491-
if (EC != object_error::invalid_file_type)
492-
reportError(Arc->getFileName(), EC.message());
491+
if (auto E = isNotObjectErrorInvalidFileType(ChildOrErr.takeError())) {
492+
std::string Buf;
493+
raw_string_ostream OS(Buf);
494+
logAllUnhandledErrors(std::move(E), OS, "");
495+
OS.flush();
496+
reportError(Arc->getFileName(), Buf);
497+
}
498+
ChildOrErr.takeError();
493499
continue;
494500
}
495501

0 commit comments

Comments
 (0)