forked from OSchip/llvm-project
[PECOFF] Create __ImageBase symbol.
__ImageBase is a symbol having 4 byte integer equal to the image base address of the resultant executable. The linker is expected to create the symbol as if it were read from a file. In order to emit the symbol contents only when the symbol is actually referenced, we created a pseudo library file to wrap the linker generated symbol. The library file member is emitted to the output only when the member is actually referenced, which is suitable for our purpose. llvm-svn: 188052
This commit is contained in:
parent
0ecb26a79e
commit
908606d0a9
|
@ -0,0 +1,128 @@
|
|||
//===- lib/ReaderWriter/PECOFF/LinkerGeneratedSymbolFile.cpp --------------===//
|
||||
//
|
||||
// The LLVM Linker
|
||||
//
|
||||
// This file is distributed under the University of Illinois Open Source
|
||||
// License. See LICENSE.TXT for details.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#include "Atoms.h"
|
||||
#include "GroupedSectionsPass.h"
|
||||
#include "IdataPass.h"
|
||||
|
||||
#include "llvm/ADT/SmallString.h"
|
||||
#include "llvm/Support/Allocator.h"
|
||||
#include "llvm/Support/Path.h"
|
||||
#include "lld/Core/ArchiveLibraryFile.h"
|
||||
#include "lld/Core/InputFiles.h"
|
||||
#include "lld/Core/PassManager.h"
|
||||
#include "lld/Passes/LayoutPass.h"
|
||||
#include "lld/ReaderWriter/PECOFFLinkingContext.h"
|
||||
#include "lld/ReaderWriter/Reader.h"
|
||||
#include "lld/ReaderWriter/Simple.h"
|
||||
#include "lld/ReaderWriter/Writer.h"
|
||||
|
||||
namespace lld {
|
||||
namespace coff {
|
||||
|
||||
namespace {
|
||||
|
||||
// The symbol ___ImageBase is a linker generated symbol. No standard library
|
||||
// files define it, but the linker is expected to prepare it as if it was read
|
||||
// from a file. The content of the atom is a 4-byte integer equal to the image
|
||||
// base address.
|
||||
class ImageBaseAtom : public COFFLinkerInternalAtom {
|
||||
public:
|
||||
ImageBaseAtom(const File &file, uint32_t imageBase)
|
||||
: COFFLinkerInternalAtom(file, assembleRawContent(imageBase)) {}
|
||||
|
||||
virtual StringRef name() const { return "___ImageBase"; }
|
||||
virtual uint64_t ordinal() const { return 0; }
|
||||
virtual ContentType contentType() const { return typeData; }
|
||||
virtual ContentPermissions permissions() const { return permRW_; }
|
||||
virtual DeadStripKind deadStrip() const { return deadStripAlways; }
|
||||
|
||||
private:
|
||||
std::vector<uint8_t> assembleRawContent(uint32_t imageBase) {
|
||||
std::vector<uint8_t> data = std::vector<uint8_t>(4);
|
||||
*(reinterpret_cast<uint32_t *>(&data[0])) = imageBase;
|
||||
return data;
|
||||
}
|
||||
};
|
||||
|
||||
// The file to wrap ImageBaseAtom. This is the only member file of
|
||||
// LinkerGeneratedSymbolFile.
|
||||
class MemberFile : public SimpleFile {
|
||||
public:
|
||||
MemberFile(const PECOFFLinkingContext &context)
|
||||
: SimpleFile(context, "Member of the Linker Internal File"),
|
||||
_atom(*this, context.getBaseAddress()) {
|
||||
addAtom(_atom);
|
||||
};
|
||||
|
||||
private:
|
||||
ImageBaseAtom _atom;
|
||||
};
|
||||
|
||||
} // anonymous namespace
|
||||
|
||||
// A pseudo library file to wrap MemberFile, which in turn wraps ImageBaseAtom.
|
||||
// The file the core linker handle is this.
|
||||
//
|
||||
// The reason why we don't pass MemberFile to the core linker is because, if we
|
||||
// did so, ImageBaseAtom would always be emit to the resultant executable. By
|
||||
// wrapping the file by a library file, we made it to emit ImageBaseAtom only
|
||||
// when the atom is really referenced.
|
||||
class LinkerGeneratedSymbolFile : public ArchiveLibraryFile {
|
||||
public:
|
||||
LinkerGeneratedSymbolFile(const PECOFFLinkingContext &context)
|
||||
: ArchiveLibraryFile(context, "Linker Internal File"),
|
||||
_memberFile(context) {};
|
||||
|
||||
virtual const File *find(StringRef name, bool dataSymbolOnly) const {
|
||||
if (name == "___ImageBase")
|
||||
return &_memberFile;
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
virtual const atom_collection<DefinedAtom> &defined() const {
|
||||
return _noDefinedAtoms;
|
||||
}
|
||||
|
||||
virtual const atom_collection<UndefinedAtom> &undefined() const {
|
||||
return _noUndefinedAtoms;
|
||||
}
|
||||
|
||||
virtual const atom_collection<SharedLibraryAtom> &sharedLibrary() const {
|
||||
return _noSharedLibraryAtoms;
|
||||
}
|
||||
|
||||
virtual const atom_collection<AbsoluteAtom> &absolute() const {
|
||||
return _noAbsoluteAtoms;
|
||||
}
|
||||
|
||||
private:
|
||||
MemberFile _memberFile;
|
||||
};
|
||||
|
||||
/// An instance of UndefinedSymbolFile has a list of undefined symbols
|
||||
/// specified by "/include" command line option. This will be added to the
|
||||
/// input file list to force the core linker to try to resolve the undefined
|
||||
/// symbols.
|
||||
class UndefinedSymbolFile : public SimpleFile {
|
||||
public:
|
||||
UndefinedSymbolFile(const LinkingContext &ti)
|
||||
: SimpleFile(ti, "Linker Internal File") {
|
||||
for (StringRef symbol : ti.initialUndefinedSymbols()) {
|
||||
UndefinedAtom *atom = new (_alloc) coff::COFFUndefinedAtom(*this, symbol);
|
||||
addAtom(*atom);
|
||||
}
|
||||
}
|
||||
|
||||
private:
|
||||
llvm::BumpPtrAllocator _alloc;
|
||||
};
|
||||
|
||||
} // end namespace coff
|
||||
} // end namespace lld
|
|
@ -10,6 +10,7 @@
|
|||
#include "Atoms.h"
|
||||
#include "GroupedSectionsPass.h"
|
||||
#include "IdataPass.h"
|
||||
#include "LinkerGeneratedSymbolFile.h"
|
||||
|
||||
#include "llvm/ADT/SmallString.h"
|
||||
#include "llvm/Support/Allocator.h"
|
||||
|
@ -30,24 +31,6 @@ bool containDirectoryName(StringRef path) {
|
|||
llvm::sys::path::remove_filename(smallStr);
|
||||
return !smallStr.str().empty();
|
||||
}
|
||||
|
||||
/// An instance of UndefinedSymbolFile has a list of undefined symbols
|
||||
/// specified by "/include" command line option. This will be added to the
|
||||
/// input file list to force the core linker to try to resolve the undefined
|
||||
/// symbols.
|
||||
class UndefinedSymbolFile : public SimpleFile {
|
||||
public:
|
||||
UndefinedSymbolFile(const LinkingContext &ti)
|
||||
: SimpleFile(ti, "Linker Internal File") {
|
||||
for (StringRef symbol : ti.initialUndefinedSymbols()) {
|
||||
UndefinedAtom *atom = new (_alloc) coff::COFFUndefinedAtom(*this, symbol);
|
||||
addAtom(*atom);
|
||||
}
|
||||
}
|
||||
|
||||
private:
|
||||
llvm::BumpPtrAllocator _alloc;
|
||||
};
|
||||
} // anonymous namespace
|
||||
|
||||
error_code PECOFFLinkingContext::parseFile(
|
||||
|
@ -83,8 +66,11 @@ bool PECOFFLinkingContext::validateImpl(raw_ostream &diagnostics) {
|
|||
|
||||
void PECOFFLinkingContext::addImplicitFiles(InputFiles &files) const {
|
||||
// Add a pseudo file for "/include" linker option.
|
||||
auto *file = new (_alloc) UndefinedSymbolFile(*this);
|
||||
files.prependFile(*file);
|
||||
auto *undefFile = new (_alloc) coff::UndefinedSymbolFile(*this);
|
||||
files.prependFile(*undefFile);
|
||||
|
||||
auto *linkerFile = new (_alloc) coff::LinkerGeneratedSymbolFile(*this);
|
||||
files.appendFile(*linkerFile);
|
||||
}
|
||||
|
||||
/// Append the given file to the input file list. The file must be an object
|
||||
|
|
|
@ -0,0 +1,59 @@
|
|||
---
|
||||
header:
|
||||
Machine: IMAGE_FILE_MACHINE_I386
|
||||
Characteristics: [ ]
|
||||
sections:
|
||||
- Name: .text
|
||||
Characteristics: [ IMAGE_SCN_CNT_CODE, IMAGE_SCN_MEM_EXECUTE, IMAGE_SCN_MEM_READ ]
|
||||
Alignment: 16
|
||||
SectionData: A100000000C3
|
||||
Relocations:
|
||||
- VirtualAddress: 1
|
||||
SymbolName: ___ImageBase
|
||||
Type: IMAGE_REL_I386_DIR32
|
||||
- Name: .data
|
||||
Characteristics: [ IMAGE_SCN_CNT_INITIALIZED_DATA, IMAGE_SCN_MEM_READ, IMAGE_SCN_MEM_WRITE ]
|
||||
Alignment: 16
|
||||
SectionData: ""
|
||||
- Name: .drectve
|
||||
Characteristics: [ IMAGE_SCN_LNK_INFO, IMAGE_SCN_LNK_REMOVE ]
|
||||
Alignment: 2147483648
|
||||
SectionData: 2F454E5452593A5F737461727420
|
||||
symbols:
|
||||
- Name: .text
|
||||
Value: 0
|
||||
SectionNumber: 1
|
||||
SimpleType: IMAGE_SYM_TYPE_NULL
|
||||
ComplexType: IMAGE_SYM_DTYPE_NULL
|
||||
StorageClass: IMAGE_SYM_CLASS_STATIC
|
||||
NumberOfAuxSymbols: 1
|
||||
AuxiliaryData: 060000000100000000000000000000000000
|
||||
- Name: .data
|
||||
Value: 0
|
||||
SectionNumber: 2
|
||||
SimpleType: IMAGE_SYM_TYPE_NULL
|
||||
ComplexType: IMAGE_SYM_DTYPE_NULL
|
||||
StorageClass: IMAGE_SYM_CLASS_STATIC
|
||||
NumberOfAuxSymbols: 1
|
||||
AuxiliaryData: 000000000000000000000000000000000000
|
||||
- Name: ___ImageBase
|
||||
Value: 0
|
||||
SectionNumber: 0
|
||||
SimpleType: IMAGE_SYM_TYPE_NULL
|
||||
ComplexType: IMAGE_SYM_DTYPE_NULL
|
||||
StorageClass: IMAGE_SYM_CLASS_EXTERNAL
|
||||
- Name: __start
|
||||
Value: 0
|
||||
SectionNumber: 1
|
||||
SimpleType: IMAGE_SYM_TYPE_NULL
|
||||
ComplexType: IMAGE_SYM_DTYPE_NULL
|
||||
StorageClass: IMAGE_SYM_CLASS_EXTERNAL
|
||||
- Name: .drectve
|
||||
Value: 0
|
||||
SectionNumber: 3
|
||||
SimpleType: IMAGE_SYM_TYPE_NULL
|
||||
ComplexType: IMAGE_SYM_DTYPE_NULL
|
||||
StorageClass: IMAGE_SYM_CLASS_STATIC
|
||||
NumberOfAuxSymbols: 1
|
||||
AuxiliaryData: 0E0000000000000000000000000000000000
|
||||
...
|
|
@ -0,0 +1,10 @@
|
|||
# RUN: yaml2obj %p/Inputs/imagebase.obj.yaml > %t.obj
|
||||
#
|
||||
# RUN: lld -flavor link /out:%t1 /subsystem:console -- %t.obj \
|
||||
# RUN: && llvm-objdump -disassemble %t1 | FileCheck -check-prefix=CHECK1 %s
|
||||
#
|
||||
# RUN: lld -flavor link /out:%t1 /subsystem:console /base:65536 -- %t.obj \
|
||||
# RUN: && llvm-objdump -disassemble %t1 | FileCheck -check-prefix=CHECK2 %s
|
||||
|
||||
CHECK1: a1 00 20 40 00 movl 4202496, %eax
|
||||
CHECK2: a1 00 20 01 00 movl 73728, %eax
|
Loading…
Reference in New Issue