[MachO] Begin to add some MachO specific File/Atoms, and add the start of

normalizedToAtoms.

llvm-svn: 198459
This commit is contained in:
Joey Gouly 2014-01-03 23:12:02 +00:00
parent 0724bf6767
commit ceb16dedef
9 changed files with 234 additions and 7 deletions

View File

@ -0,0 +1,41 @@
//===- lib/ReaderWriter/MachO/Atoms.h -------------------------------------===//
//
// The LLVM Linker
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
#ifndef LLD_READER_WRITER_MACHO_ATOMS_H
#define LLD_READER_WRITER_MACHO_ATOMS_H
#include "lld/ReaderWriter/Simple.h"
namespace lld {
namespace mach_o {
class MachODefinedAtom : public SimpleDefinedAtom {
public:
// FIXME: This constructor should also take the ContentType.
MachODefinedAtom(const File &f, const StringRef name,
const ArrayRef<uint8_t> content)
: SimpleDefinedAtom(f), _name(name), _content(content) {}
virtual uint64_t size() const { return rawContent().size(); }
virtual ContentType contentType() const { return DefinedAtom::typeCode; }
virtual StringRef name() const { return _name; }
virtual Scope scope() const { return scopeGlobal; }
virtual ArrayRef<uint8_t> rawContent() const { return _content; }
private:
const StringRef _name;
const ArrayRef<uint8_t> _content;
};
} // mach_o
} // lld
#endif

View File

@ -3,6 +3,7 @@ add_lld_library(lldMachO
MachONormalizedFileBinaryReader.cpp
MachONormalizedFileBinaryWriter.cpp
MachONormalizedFileFromAtoms.cpp
MachONormalizedFileToAtoms.cpp
MachONormalizedFileYAML.cpp
ReferenceKinds.cpp
WriterMachO.cpp
@ -12,3 +13,5 @@ target_link_libraries(lldMachO
lldReaderWriter
lldPasses
)
include_directories(.)

View File

@ -0,0 +1,37 @@
//===- lib/ReaderWriter/MachO/File.h --------------------------------------===//
//
// The LLVM Linker
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
#ifndef LLD_READER_WRITER_MACHO_FILE_H
#define LLD_READER_WRITER_MACHO_FILE_H
#include "Atoms.h"
#include "lld/ReaderWriter/Simple.h"
namespace lld {
namespace mach_o {
class MachOFile : public SimpleFile {
public:
MachOFile(StringRef path) : SimpleFile(path) {}
void addDefinedAtom(StringRef name, ArrayRef<uint8_t> content) {
MachODefinedAtom *atom =
new (_allocator) MachODefinedAtom(*this, name, content);
addAtom(*atom);
}
private:
llvm::BumpPtrAllocator _allocator;
};
} // end namespace mach_o
} // end namespace lld
#endif

View File

@ -113,7 +113,7 @@ struct Section {
SectionAttr attributes;
uint32_t alignment;
Hex64 address;
ContentBytes content;
std::vector<uint8_t> content;
Relocations relocations;
IndirectSymbols indirectSymbols;
};
@ -273,7 +273,3 @@ normalizedFromAtoms(const lld::File &atomFile, const MachOLinkingContext &ctxt);
} // namespace lld
#endif // LLD_READER_WRITER_MACHO_NORMALIZE_FILE_H

View File

@ -423,7 +423,7 @@ void Util::appendSection(SectionInfo *si, NormalizedFile &file) {
// Copy content from atoms to content buffer for section.
// FIXME: zerofill atoms/sections should not take up content space.
normSect->content.resize(si->size);
Hex8 *sectionContent = normSect->content.data();
uint8_t *sectionContent = normSect->content.data();
for (AtomInfo &ai : si->atomsAndOffsets) {
// Copy raw bytes.
uint8_t *atomContent = reinterpret_cast<uint8_t*>

View File

@ -0,0 +1,66 @@
//===- lib/ReaderWriter/MachO/MachONormalizedFileToAtoms.cpp --------------===//
//
// The LLVM Linker
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
///
/// \file Converts from in-memory normalized mach-o to in-memory Atoms.
///
/// +------------+
/// | normalized |
/// +------------+
/// |
/// |
/// v
/// +-------+
/// | Atoms |
/// +-------+
#include "MachONormalizedFile.h"
#include "File.h"
#include "Atoms.h"
#include "lld/Core/LLVM.h"
#include "llvm/Support/MachO.h"
using namespace llvm::MachO;
namespace lld {
namespace mach_o {
namespace normalized {
static ErrorOr<std::unique_ptr<lld::File>>
normalizedObjectToAtoms(const NormalizedFile &normalizedFile, StringRef path) {
std::unique_ptr<MachOFile> file(new MachOFile(path));
for (auto &sym : normalizedFile.globalSymbols) {
file->addDefinedAtom(sym.name,
normalizedFile.sections[sym.sect - 1].content);
}
assert(normalizedFile.localSymbols.empty() &&
"local symbols not supported yet!");
assert(normalizedFile.undefinedSymbols.empty() &&
"undefined symbols not supported yet!");
return std::unique_ptr<File>(std::move(file));
}
ErrorOr<std::unique_ptr<lld::File>>
normalizedToAtoms(const NormalizedFile &normalizedFile, StringRef path) {
switch (normalizedFile.fileType) {
case MH_OBJECT:
return normalizedObjectToAtoms(normalizedFile, path);
default:
llvm_unreachable("unhandled MachO file type!");
}
}
} // namespace normalized
} // namespace mach_o
} // namespace lld

View File

@ -269,6 +269,7 @@ struct ScalarBitSetTraits<SymbolDesc> {
template <>
struct MappingTraits<Section> {
struct NormalizedContentBytes;
static void mapping(IO &io, Section &sect) {
io.mapRequired("segment", sect.segmentName);
io.mapRequired("section", sect.sectionName);
@ -276,10 +277,31 @@ struct MappingTraits<Section> {
io.mapOptional("attributes", sect.attributes);
io.mapOptional("alignment", sect.alignment, 0U);
io.mapRequired("address", sect.address);
io.mapOptional("content", sect.content);
MappingNormalization<NormalizedContent, std::vector<uint8_t>> content(
io, sect.content);
io.mapOptional("content", content->normalizedContent);
io.mapOptional("relocations", sect.relocations);
io.mapOptional("indirect-syms", sect.indirectSymbols);
}
// FIXME: It would be good if we could remove this, so we don't need to copy
// the content data.
struct NormalizedContent {
NormalizedContent(IO &) {}
NormalizedContent(IO &, std::vector<uint8_t> content) {
for (auto &c : content) {
normalizedContent.push_back(c);
}
}
std::vector<uint8_t> denormalize(IO &) {
std::vector<uint8_t> content;
for (auto &c : normalizedContent) {
content.push_back(c);
}
return content;
}
ContentBytes normalizedContent;
};
};

View File

@ -2,6 +2,7 @@
add_lld_unittest(lldMachOTests
MachONormalizedFileBinaryReaderTests.cpp
MachONormalizedFileBinaryWriterTests.cpp
MachONormalizedFileToAtomsTests.cpp
MachONormalizedFileYAMLTests.cpp
)

View File

@ -0,0 +1,61 @@
//===- lld/unittest/MachOTests/MachONormalizedFileToAtomsTests.cpp --------===//
//
// The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
#include "gtest/gtest.h"
#include <llvm/Support/MachO.h>
#include "../../lib/ReaderWriter/MachO/MachONormalizedFile.h"
#include <assert.h>
#include <vector>
using llvm::ErrorOr;
using namespace lld::mach_o::normalized;
using namespace llvm::MachO;
unsigned countDefinedAtoms(const lld::File &file) {
unsigned count = 0;
for (const auto &d : file.defined()) {
(void)d;
++count;
}
return count;
}
TEST(ToAtomsTest, empty_obj_x86_64) {
NormalizedFile f;
f.arch = lld::MachOLinkingContext::arch_x86_64;
ErrorOr<std::unique_ptr<const lld::File>> atom_f = normalizedToAtoms(f, "");
EXPECT_FALSE(!atom_f);
EXPECT_EQ(0U, countDefinedAtoms(**atom_f));
}
TEST(ToAtomsTest, basic_obj_x86_64) {
NormalizedFile f;
f.arch = lld::MachOLinkingContext::arch_x86_64;
Section textSection;
static const uint8_t contentBytes[] = { 0x55, 0x48, 0x89, 0xE5,
0x31, 0xC0, 0x5D, 0xC3 };
const unsigned contentSize = sizeof(contentBytes) / sizeof(contentBytes[0]);
textSection.content.insert(textSection.content.begin(), contentBytes,
&contentBytes[contentSize]);
f.sections.push_back(textSection);
Symbol mainSymbol;
mainSymbol.name = "_main";
mainSymbol.type = N_SECT;
mainSymbol.sect = 1;
f.globalSymbols.push_back(mainSymbol);
ErrorOr<std::unique_ptr<const lld::File>> atom_f = normalizedToAtoms(f, "");
EXPECT_FALSE(!atom_f);
EXPECT_EQ(1U, countDefinedAtoms(**atom_f));
const lld::DefinedAtom *singleAtom = *(*atom_f)->defined().begin();
llvm::ArrayRef<uint8_t> atomContent(singleAtom->rawContent());
EXPECT_EQ(0, memcmp(atomContent.data(), contentBytes, contentSize));
}