summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorRui Ueyama <ruiu@google.com>2013-08-09 04:44:15 +0000
committerRui Ueyama <ruiu@google.com>2013-08-09 04:44:15 +0000
commit908606d0a9194b9097a081e548ce43e12617a4db (patch)
treedfda78079ca85ea5ea0e1af0c8be3936bde5b49d
parent0ecb26a79e39149be95562240e03686421cd84c2 (diff)
downloadbcm5719-llvm-908606d0a9194b9097a081e548ce43e12617a4db.tar.gz
bcm5719-llvm-908606d0a9194b9097a081e548ce43e12617a4db.zip
[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
-rw-r--r--lld/lib/ReaderWriter/PECOFF/LinkerGeneratedSymbolFile.h128
-rw-r--r--lld/lib/ReaderWriter/PECOFF/PECOFFLinkingContext.cpp26
-rw-r--r--lld/test/pecoff/Inputs/imagebase.obj.yaml59
-rw-r--r--lld/test/pecoff/imagebase.test10
4 files changed, 203 insertions, 20 deletions
diff --git a/lld/lib/ReaderWriter/PECOFF/LinkerGeneratedSymbolFile.h b/lld/lib/ReaderWriter/PECOFF/LinkerGeneratedSymbolFile.h
new file mode 100644
index 00000000000..5f39fd207d4
--- /dev/null
+++ b/lld/lib/ReaderWriter/PECOFF/LinkerGeneratedSymbolFile.h
@@ -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
diff --git a/lld/lib/ReaderWriter/PECOFF/PECOFFLinkingContext.cpp b/lld/lib/ReaderWriter/PECOFF/PECOFFLinkingContext.cpp
index ad0d563d86a..4dbb5d70a46 100644
--- a/lld/lib/ReaderWriter/PECOFF/PECOFFLinkingContext.cpp
+++ b/lld/lib/ReaderWriter/PECOFF/PECOFFLinkingContext.cpp
@@ -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
diff --git a/lld/test/pecoff/Inputs/imagebase.obj.yaml b/lld/test/pecoff/Inputs/imagebase.obj.yaml
new file mode 100644
index 00000000000..cd593571b8b
--- /dev/null
+++ b/lld/test/pecoff/Inputs/imagebase.obj.yaml
@@ -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
+...
diff --git a/lld/test/pecoff/imagebase.test b/lld/test/pecoff/imagebase.test
new file mode 100644
index 00000000000..206a525c725
--- /dev/null
+++ b/lld/test/pecoff/imagebase.test
@@ -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
OpenPOWER on IntegriCloud