# Check we report this.
# RUN: yaml2obj %s -o %t.o
-# RUN: llvm-ar rcs %t.a %t.o
+# RUN: llvm-ar rcS %t.a %t.o
# RUN: not ld.lld --whole-archive %t.a -o /dev/null 2>&1 | FileCheck %s
# CHECK: {{.*}}.a({{.*}}.o): corrupted ELF file: invalid data encoding
## EV_CURRENT(1), ELFOSABI_LINUX(3), <padding zero bytes>, ET_REL(1), EM_NONE(0)
# RUN: echo -e -n "\x7f\x45\x4c\x46\x00\x01\x01\x03\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00" > %t/invalid.o
-# RUN: llvm-ar --format=gnu cr %t/invalid-class.a %t/invalid.o
+# RUN: llvm-ar --format=gnu crS %t/invalid-class.a %t/invalid.o
# RUN: not ld.lld -whole-archive %t/invalid-class.a -o /dev/null 2>&1 | FileCheck %s
# CHECK: invalid-class.a(invalid.o): corrupted ELF file: invalid file class
static bool classof(const Binary *v) {
return v->isSymbolic();
}
+
+ static bool isSymbolicFile(file_magic Type, const LLVMContext *Context);
};
inline BasicSymbolRef::BasicSymbolRef(DataRefImpl SymbolP,
// reference to it, thus SymbolicFile should be destroyed first.
LLVMContext Context;
std::unique_ptr<object::SymbolicFile> Obj;
- if (identify_magic(Buf.getBuffer()) == file_magic::bitcode) {
+
+ const file_magic Type = identify_magic(Buf.getBuffer());
+ // Treat unsupported file types as having no symbols.
+ if (!object::SymbolicFile::isSymbolicFile(Type, &Context))
+ return Ret;
+ if (Type == file_magic::bitcode) {
auto ObjOrErr = object::SymbolicFile::createSymbolicFile(
Buf, file_magic::bitcode, &Context);
- if (!ObjOrErr) {
- // FIXME: check only for "not an object file" errors.
- consumeError(ObjOrErr.takeError());
- return Ret;
- }
+ if (!ObjOrErr)
+ return ObjOrErr.takeError();
Obj = std::move(*ObjOrErr);
} else {
auto ObjOrErr = object::SymbolicFile::createSymbolicFile(Buf);
- if (!ObjOrErr) {
- // FIXME: check only for "not an object file" errors.
- consumeError(ObjOrErr.takeError());
- return Ret;
- }
+ if (!ObjOrErr)
+ return ObjOrErr.takeError();
Obj = std::move(*ObjOrErr);
}
static Expected<std::vector<MemberData>>
computeMemberData(raw_ostream &StringTable, raw_ostream &SymNames,
object::Archive::Kind Kind, bool Thin, bool Deterministic,
- ArrayRef<NewArchiveMember> NewMembers) {
+ bool NeedSymbols, ArrayRef<NewArchiveMember> NewMembers) {
static char PaddingData[8] = {'\n', '\n', '\n', '\n', '\n', '\n', '\n', '\n'};
// This ignores the symbol table, but we only need the value mod 8 and the
ModTime, Size);
Out.flush();
- Expected<std::vector<unsigned>> Symbols =
- getSymbols(Buf, SymNames, HasObject);
- if (auto E = Symbols.takeError())
- return std::move(E);
+ std::vector<unsigned> Symbols;
+ if (NeedSymbols) {
+ Expected<std::vector<unsigned>> SymbolsOrErr =
+ getSymbols(Buf, SymNames, HasObject);
+ if (auto E = SymbolsOrErr.takeError())
+ return std::move(E);
+ Symbols = std::move(*SymbolsOrErr);
+ }
Pos += Header.size() + Data.size() + Padding.size();
- Ret.push_back({std::move(*Symbols), std::move(Header), Data, Padding});
+ Ret.push_back({std::move(Symbols), std::move(Header), Data, Padding});
}
// If there are no symbols, emit an empty symbol table, to satisfy Solaris
// tools, older versions of which expect a symbol table in a non-empty
SmallString<0> StringTableBuf;
raw_svector_ostream StringTable(StringTableBuf);
- Expected<std::vector<MemberData>> DataOrErr = computeMemberData(
- StringTable, SymNames, Kind, Thin, Deterministic, NewMembers);
+ Expected<std::vector<MemberData>> DataOrErr =
+ computeMemberData(StringTable, SymNames, Kind, Thin, Deterministic,
+ WriteSymtab, NewMembers);
if (Error E = DataOrErr.takeError())
return E;
std::vector<MemberData> &Data = *DataOrErr;
if (Type == file_magic::unknown)
Type = identify_magic(Data);
+ if (!isSymbolicFile(Type, Context))
+ return errorCodeToError(object_error::invalid_file_type);
+
switch (Type) {
case file_magic::bitcode:
- if (Context)
- return IRObjectFile::create(Object, *Context);
- LLVM_FALLTHROUGH;
- case file_magic::unknown:
- case file_magic::archive:
- case file_magic::coff_cl_gl_object:
- case file_magic::macho_universal_binary:
- case file_magic::windows_resource:
- case file_magic::pdb:
- case file_magic::minidump:
- case file_magic::tapi_file:
- return errorCodeToError(object_error::invalid_file_type);
+ // Context is guaranteed to be non-null here, because bitcode magic only
+ // indicates a symbolic file when Context is non-null.
+ return IRObjectFile::create(Object, *Context);
case file_magic::elf:
case file_magic::elf_executable:
case file_magic::elf_shared_object:
MemoryBufferRef(BCData->getBuffer(), Object.getBufferIdentifier()),
*Context);
}
+ default:
+ llvm_unreachable("Unexpected Binary File Type");
+ }
+}
+
+bool SymbolicFile::isSymbolicFile(file_magic Type, const LLVMContext *Context) {
+ switch (Type) {
+ case file_magic::bitcode:
+ return Context != nullptr;
+ case file_magic::elf:
+ case file_magic::elf_executable:
+ case file_magic::elf_shared_object:
+ case file_magic::elf_core:
+ case file_magic::macho_executable:
+ case file_magic::macho_fixed_virtual_memory_shared_lib:
+ case file_magic::macho_core:
+ case file_magic::macho_preload_executable:
+ case file_magic::macho_dynamically_linked_shared_lib:
+ case file_magic::macho_dynamic_linker:
+ case file_magic::macho_bundle:
+ case file_magic::macho_dynamically_linked_shared_lib_stub:
+ case file_magic::macho_dsym_companion:
+ case file_magic::macho_kext_bundle:
+ case file_magic::pecoff_executable:
+ case file_magic::xcoff_object_32:
+ case file_magic::xcoff_object_64:
+ case file_magic::wasm_object:
+ case file_magic::coff_import_library:
+ case file_magic::elf_relocatable:
+ case file_magic::macho_object:
+ case file_magic::coff_object:
+ return true;
+ default:
+ return false;
}
- llvm_unreachable("Unexpected Binary File Type");
}
--- /dev/null
+## Show that the archive library emits error messages when adding malformed
+## objects.
+
+# RUN: rm -rf %t.dir
+# RUN: split-file %s %t.dir
+# RUN: cd %t.dir
+
+## Malformed bitcode object.
+# RUN: llvm-as input.ll -o input.bc
+# RUN: %python -c "with open('input.bc', 'a') as f: f.truncate(10)"
+# RUN: not llvm-ar rc bad.a input.bc 2>&1 | FileCheck %s --check-prefix=ERR1
+
+# ERR1: error: bad.a: Invalid bitcode signature
+
+## Non-bitcode malformed file.
+# RUN: yaml2obj input.yaml -o input.o
+# RUN: not llvm-ar rc bad.a input.o 2>&1 | FileCheck %s --check-prefix=ERR2
+
+# ERR2: error: bad.a: section header table goes past the end of the file: e_shoff = 0x9999
+
+## Don't emit an error if the symbol table is not required.
+# RUN: llvm-ar rcS good.a input.o input.bc
+# RUN: llvm-ar t good.a | FileCheck %s --check-prefix=CONTENTS
+
+# CONTENTS: input.o
+# CONTENTS-NEXT: input.bc
+
+#--- input.ll
+target datalayout = "e-m:w-i64:64-f80:128-n8:16:32:64-S128"
+target triple = "x86_64-pc-linux"
+
+#--- input.yaml
+--- !ELF
+FileHeader:
+ Class: ELFCLASS64
+ Data: ELFDATA2LSB
+ Type: ET_REL
+ EShOff: 0x9999
--- /dev/null
+## Show that the archive library does not emit an error or add any symbols to
+## the archive symbol table, when it encounters an unknown file type, but still
+## adds the file to the archive.
+
+# RUN: echo something > %t
+# RUN: rm -f %t.a
+# RUN: llvm-ar rc %t.a %t
+# RUN: llvm-ar t %t.a | FileCheck %s --check-prefix=CONTENTS -DFILE=%basename_t
+# RUN: llvm-nm --print-armap %t.a | FileCheck %s --allow-empty --implicit-check-not={{.}}
+
+# CONTENTS: [[FILE]]