forked from OSchip/llvm-project
[lld-macho] Add archive name and file modtime to STABS output
We should also set the modtime when running LTO. That will be done in a future diff, together with support for the `-object_path_lto` flag. Reviewed By: clayborg Differential Revision: https://reviews.llvm.org/D91318
This commit is contained in:
parent
d0c4be42e3
commit
b768d57b36
|
@ -212,21 +212,32 @@ getFrameworkSearchPaths(opt::InputArgList &args,
|
|||
{"/Library/Frameworks", "/System/Library/Frameworks"});
|
||||
}
|
||||
|
||||
namespace {
|
||||
struct ArchiveMember {
|
||||
MemoryBufferRef mbref;
|
||||
uint32_t modTime;
|
||||
};
|
||||
} // namespace
|
||||
|
||||
// Returns slices of MB by parsing MB as an archive file.
|
||||
// Each slice consists of a member file in the archive.
|
||||
static std::vector<MemoryBufferRef> getArchiveMembers(MemoryBufferRef mb) {
|
||||
static std::vector<ArchiveMember> getArchiveMembers(MemoryBufferRef mb) {
|
||||
std::unique_ptr<Archive> file =
|
||||
CHECK(Archive::create(mb),
|
||||
mb.getBufferIdentifier() + ": failed to parse archive");
|
||||
|
||||
std::vector<MemoryBufferRef> v;
|
||||
std::vector<ArchiveMember> v;
|
||||
Error err = Error::success();
|
||||
for (const Archive::Child &c : file->children(err)) {
|
||||
MemoryBufferRef mbref =
|
||||
CHECK(c.getMemoryBufferRef(),
|
||||
mb.getBufferIdentifier() +
|
||||
": could not get the buffer for a child of the archive");
|
||||
v.push_back(mbref);
|
||||
uint32_t modTime = toTimeT(
|
||||
CHECK(c.getLastModified(), mb.getBufferIdentifier() +
|
||||
": could not get the modification "
|
||||
"time for a child of the archive"));
|
||||
v.push_back({mbref, modTime});
|
||||
}
|
||||
if (err)
|
||||
fatal(mb.getBufferIdentifier() +
|
||||
|
@ -235,6 +246,16 @@ static std::vector<MemoryBufferRef> getArchiveMembers(MemoryBufferRef mb) {
|
|||
return v;
|
||||
}
|
||||
|
||||
static void forceLoadArchive(StringRef path) {
|
||||
if (Optional<MemoryBufferRef> buffer = readFile(path)) {
|
||||
for (const ArchiveMember &member : getArchiveMembers(*buffer)) {
|
||||
auto file = make<ObjFile>(member.mbref, member.modTime);
|
||||
file->archiveName = buffer->getBufferIdentifier();
|
||||
inputFiles.push_back(file);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static InputFile *addFile(StringRef path) {
|
||||
Optional<MemoryBufferRef> buffer = readFile(path);
|
||||
if (!buffer)
|
||||
|
@ -251,9 +272,7 @@ static InputFile *addFile(StringRef path) {
|
|||
error(path + ": archive has no index; run ranlib to add one");
|
||||
|
||||
if (config->allLoad) {
|
||||
if (Optional<MemoryBufferRef> buffer = readFile(path))
|
||||
for (MemoryBufferRef member : getArchiveMembers(*buffer))
|
||||
inputFiles.push_back(make<ObjFile>(member));
|
||||
forceLoadArchive(path);
|
||||
} else if (config->forceLoadObjC) {
|
||||
for (const object::Archive::Symbol &sym : file->symbols())
|
||||
if (sym.getName().startswith(objc::klass))
|
||||
|
@ -264,16 +283,16 @@ static InputFile *addFile(StringRef path) {
|
|||
// consider creating a LazyObjFile class in order to avoid double-loading
|
||||
// these files here and below (as part of the ArchiveFile).
|
||||
if (Optional<MemoryBufferRef> buffer = readFile(path))
|
||||
for (MemoryBufferRef member : getArchiveMembers(*buffer))
|
||||
if (hasObjCSection(member))
|
||||
inputFiles.push_back(make<ObjFile>(member));
|
||||
for (const ArchiveMember &member : getArchiveMembers(*buffer))
|
||||
if (hasObjCSection(member.mbref))
|
||||
inputFiles.push_back(make<ObjFile>(member.mbref, member.modTime));
|
||||
}
|
||||
|
||||
newFile = make<ArchiveFile>(std::move(file));
|
||||
break;
|
||||
}
|
||||
case file_magic::macho_object:
|
||||
newFile = make<ObjFile>(mbref);
|
||||
newFile = make<ObjFile>(mbref, getModTime(path));
|
||||
break;
|
||||
case file_magic::macho_dynamically_linked_shared_lib:
|
||||
case file_magic::macho_dynamically_linked_shared_lib_stub:
|
||||
|
@ -304,12 +323,6 @@ static void addFileList(StringRef path) {
|
|||
addFile(path);
|
||||
}
|
||||
|
||||
static void forceLoadArchive(StringRef path) {
|
||||
if (Optional<MemoryBufferRef> buffer = readFile(path))
|
||||
for (MemoryBufferRef member : getArchiveMembers(*buffer))
|
||||
inputFiles.push_back(make<ObjFile>(member));
|
||||
}
|
||||
|
||||
static std::array<StringRef, 6> archNames{"arm", "arm64", "i386",
|
||||
"x86_64", "ppc", "ppc64"};
|
||||
static bool isArchString(StringRef s) {
|
||||
|
|
|
@ -43,6 +43,8 @@ llvm::Optional<std::string> resolveDylibPath(llvm::StringRef path);
|
|||
llvm::Optional<DylibFile *> makeDylibFromTAPI(llvm::MemoryBufferRef mbref,
|
||||
DylibFile *umbrella = nullptr);
|
||||
|
||||
uint32_t getModTime(llvm::StringRef path);
|
||||
|
||||
} // namespace macho
|
||||
} // namespace lld
|
||||
|
||||
|
|
|
@ -175,3 +175,13 @@ Optional<DylibFile *> macho::makeDylibFromTAPI(MemoryBufferRef mbref,
|
|||
}
|
||||
return make<DylibFile>(**result, umbrella);
|
||||
}
|
||||
|
||||
uint32_t macho::getModTime(StringRef path) {
|
||||
fs::file_status stat;
|
||||
if (!fs::status(path, stat))
|
||||
if (fs::exists(stat))
|
||||
return toTimeT(stat.getLastModificationTime());
|
||||
|
||||
warn("failed to get modification time of " + path);
|
||||
return 0;
|
||||
}
|
||||
|
|
|
@ -364,7 +364,8 @@ OpaqueFile::OpaqueFile(MemoryBufferRef mb, StringRef segName,
|
|||
subsections.push_back({{0, isec}});
|
||||
}
|
||||
|
||||
ObjFile::ObjFile(MemoryBufferRef mb) : InputFile(ObjKind, mb) {
|
||||
ObjFile::ObjFile(MemoryBufferRef mb, uint32_t modTime)
|
||||
: InputFile(ObjKind, mb), modTime(modTime) {
|
||||
auto *buf = reinterpret_cast<const uint8_t *>(mb.getBufferStart());
|
||||
auto *hdr = reinterpret_cast<const mach_header_64 *>(mb.getBufferStart());
|
||||
|
||||
|
@ -592,7 +593,16 @@ void ArchiveFile::fetch(const object::Archive::Symbol &sym) {
|
|||
toString(this) +
|
||||
": could not get the buffer for the member defining symbol " +
|
||||
sym.getName());
|
||||
auto file = make<ObjFile>(mb);
|
||||
|
||||
uint32_t modTime = toTimeT(
|
||||
CHECK(c.getLastModified(), toString(this) +
|
||||
": could not get the modification time "
|
||||
"for the member defining symbol " +
|
||||
sym.getName()));
|
||||
|
||||
auto file = make<ObjFile>(mb, modTime);
|
||||
file->archiveName = getName();
|
||||
|
||||
symbols.insert(symbols.end(), file->symbols.begin(), file->symbols.end());
|
||||
subsections.insert(subsections.end(), file->subsections.begin(),
|
||||
file->subsections.end());
|
||||
|
|
|
@ -90,10 +90,12 @@ private:
|
|||
// .o file
|
||||
class ObjFile : public InputFile {
|
||||
public:
|
||||
explicit ObjFile(MemoryBufferRef mb);
|
||||
explicit ObjFile(MemoryBufferRef mb, uint32_t modTime);
|
||||
static bool classof(const InputFile *f) { return f->kind() == ObjKind; }
|
||||
|
||||
llvm::DWARFUnit *compileUnit = nullptr;
|
||||
StringRef archiveName = "";
|
||||
const uint32_t modTime;
|
||||
|
||||
private:
|
||||
void parseDebugInfo();
|
||||
|
|
|
@ -73,10 +73,12 @@ std::vector<ObjFile *> BitcodeCompiler::compile() {
|
|||
saveBuffer(buf[i], config->outputFile + Twine(i) + ".lto.o");
|
||||
}
|
||||
|
||||
// TODO: set modTime properly
|
||||
std::vector<ObjFile *> ret;
|
||||
for (unsigned i = 0; i != maxTasks; ++i)
|
||||
if (!buf[i].empty())
|
||||
ret.push_back(make<ObjFile>(MemoryBufferRef(buf[i], "lto.tmp")));
|
||||
ret.push_back(
|
||||
make<ObjFile>(MemoryBufferRef(buf[i], "lto.tmp"), /*modTime=*/0));
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
|
|
@ -602,13 +602,18 @@ void SymtabSection::emitEndSourceStab() {
|
|||
void SymtabSection::emitObjectFileStab(ObjFile *file) {
|
||||
StabsEntry stab(MachO::N_OSO);
|
||||
stab.sect = target->cpuSubtype;
|
||||
SmallString<261> path(file->getName());
|
||||
SmallString<261> path(!file->archiveName.empty() ? file->archiveName
|
||||
: file->getName());
|
||||
std::error_code ec = sys::fs::make_absolute(path);
|
||||
if (ec)
|
||||
fatal("failed to get absolute path for " + file->getName());
|
||||
fatal("failed to get absolute path for " + path);
|
||||
|
||||
if (!file->archiveName.empty())
|
||||
path.append({"(", file->getName(), ")"});
|
||||
|
||||
stab.strx = stringTableSection.addString(saver.save(path.str()));
|
||||
stab.desc = 1;
|
||||
stab.value = file->modTime;
|
||||
stabs.emplace_back(std::move(stab));
|
||||
}
|
||||
|
||||
|
|
|
@ -3,22 +3,35 @@
|
|||
# RUN: split-file %s %t
|
||||
# RUN: llvm-mc -filetype=obj -triple=x86_64-apple-darwin %t/test.s -o %t/test.o
|
||||
# RUN: llvm-mc -filetype=obj -triple=x86_64-apple-darwin %t/foo.s -o %t/foo.o
|
||||
## Set modtimes of the files for deterministic test output.
|
||||
# RUN: env TZ=UTC touch -t "197001010000.16" %t/test.o
|
||||
# RUN: env TZ=UTC touch -t "197001010000.32" %t/foo.o
|
||||
# RUN: rm -f %t/foo.a
|
||||
# RUN: llvm-ar rcsU %t/foo.a %t/foo.o
|
||||
|
||||
# RUN: %lld -lSystem %t/test.o %t/foo.o -o %t/test
|
||||
# RUN: llvm-nm -pa %t/test | FileCheck %s -DDIR=%t
|
||||
# RUN: llvm-nm -pa %t/test | FileCheck %s -DDIR=%t -DFOO_PATH=%t/foo.o
|
||||
|
||||
## Check that we emit the right modtime even when the object file is in an
|
||||
## archive.
|
||||
# RUN: %lld -lSystem %t/test.o %t/foo.a -o %t/test
|
||||
# RUN: llvm-nm -pa %t/test | FileCheck %s -DDIR=%t -DFOO_PATH=%t/foo.a\(foo.o\)
|
||||
|
||||
## Check that we emit absolute paths to the object files in our OSO entries
|
||||
## even if our inputs are relative paths.
|
||||
# RUN: cd %t && %lld -lSystem test.o foo.o -o test
|
||||
# RUN: llvm-nm -pa %t/test | FileCheck %s -DDIR=%t
|
||||
# RUN: llvm-nm -pa %t/test | FileCheck %s -DDIR=%t -DFOO_PATH=%t/foo.o
|
||||
|
||||
# RUN: cd %t && %lld -lSystem %t/test.o %t/foo.a -o %t/test
|
||||
# RUN: llvm-nm -pa %t/test | FileCheck %s -DDIR=%t -DFOO_PATH=%t/foo.a\(foo.o\)
|
||||
|
||||
# CHECK: 0000000000000000 - 00 0000 SO /tmp/test.cpp
|
||||
# CHECK-NEXT: 0000000000000000 - 03 0001 OSO [[DIR]]/test.o
|
||||
# CHECK-NEXT: 0000000000000010 - 03 0001 OSO [[DIR]]/test.o
|
||||
# CHECK-NEXT: [[#%x, MAIN:]] - 01 0000 FUN _main
|
||||
# CHECK-NEXT: 0000000000000001 - 00 0000 FUN
|
||||
# CHECK-NEXT: 0000000000000006 - 00 0000 FUN
|
||||
# CHECK-NEXT: 0000000000000000 - 01 0000 SO
|
||||
# CHECK-NEXT: 0000000000000000 - 00 0000 SO /foo.cpp
|
||||
# CHECK-NEXT: 0000000000000000 - 03 0001 OSO [[DIR]]/foo.o
|
||||
# CHECK-NEXT: 0000000000000020 - 03 0001 OSO [[FOO_PATH]]
|
||||
# CHECK-NEXT: [[#%x, FOO:]] - 01 0000 FUN _foo
|
||||
# CHECK-NEXT: 0000000000000001 - 00 0000 FUN
|
||||
# CHECK-NEXT: 0000000000000000 - 01 0000 SO
|
||||
|
@ -30,6 +43,7 @@
|
|||
.globl _main
|
||||
_main:
|
||||
Lfunc_begin0:
|
||||
callq _foo
|
||||
retq
|
||||
Lfunc_end0:
|
||||
|
||||
|
|
Loading…
Reference in New Issue