From 40e22518fcb65980e4a39eb2b926bbf65ba69829 Mon Sep 17 00:00:00 2001 From: Rui Ueyama Date: Fri, 28 Aug 2015 07:40:30 +0000 Subject: [PATCH] Re-apply r246276 - Object: Teach llvm-ar to create symbol table for COFF short import files This patch includes a fix for a llvm-readobj test. With this patch, the tool does no longer print out COFF headers for the short import file, but that's probably desirable because the header for the short import file is dummy. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@246283 91177308-0d34-0410-b5e6-96231b3b80d8 --- include/llvm/Object/Binary.h | 5 ++ include/llvm/Object/COFFImportFile.h | 70 ++++++++++++++++++++++ lib/Object/SymbolicFile.cpp | 5 +- test/Object/Inputs/coff-short-import-code | Bin 0 -> 31 bytes test/Object/Inputs/coff-short-import-data | Bin 0 -> 31 bytes test/Object/archive-symtab.test | 10 ++++ test/tools/llvm-readobj/file-headers.test | 14 +---- tools/llvm-readobj/llvm-readobj.cpp | 9 +++ 8 files changed, 99 insertions(+), 14 deletions(-) create mode 100644 include/llvm/Object/COFFImportFile.h create mode 100644 test/Object/Inputs/coff-short-import-code create mode 100644 test/Object/Inputs/coff-short-import-data diff --git a/include/llvm/Object/Binary.h b/include/llvm/Object/Binary.h index a3d6d0d4d42..1ec005a970e 100644 --- a/include/llvm/Object/Binary.h +++ b/include/llvm/Object/Binary.h @@ -41,6 +41,7 @@ protected: enum { ID_Archive, ID_MachOUniversalBinary, + ID_COFFImportFile, ID_IR, // LLVM IR // Object and children. @@ -113,6 +114,10 @@ public: return TypeID == ID_COFF; } + bool isCOFFImportFile() const { + return TypeID == ID_COFFImportFile; + } + bool isIR() const { return TypeID == ID_IR; } diff --git a/include/llvm/Object/COFFImportFile.h b/include/llvm/Object/COFFImportFile.h new file mode 100644 index 00000000000..38264c604f0 --- /dev/null +++ b/include/llvm/Object/COFFImportFile.h @@ -0,0 +1,70 @@ +//===- COFFImportFile.h - COFF short import file implementation -*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// COFF short import file is a special kind of file which contains +// only symbol names for DLL-exported symbols. This class implements +// SymbolicFile interface for the file. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_OBJECT_COFF_IMPORT_FILE_H +#define LLVM_OBJECT_COFF_IMPORT_FILE_H + +#include "llvm/Object/COFF.h" +#include "llvm/Object/IRObjectFile.h" +#include "llvm/Object/ObjectFile.h" +#include "llvm/Object/SymbolicFile.h" +#include "llvm/Support/MemoryBuffer.h" + +namespace llvm { +namespace object { + +class COFFImportFile : public SymbolicFile { +public: + COFFImportFile(MemoryBufferRef Source) + : SymbolicFile(ID_COFFImportFile, Source) {} + + static inline bool classof(Binary const *V) { return V->isCOFFImportFile(); } + + void moveSymbolNext(DataRefImpl &Symb) const override { ++Symb.p; } + + std::error_code printSymbolName(raw_ostream &OS, + DataRefImpl Symb) const override { + if (Symb.p == 1) + OS << "__imp_"; + OS << StringRef(Data.getBufferStart() + sizeof(coff_import_header)); + return std::error_code(); + } + + uint32_t getSymbolFlags(DataRefImpl Symb) const override { + return SymbolRef::SF_Global; + } + + basic_symbol_iterator symbol_begin_impl() const override { + return BasicSymbolRef(DataRefImpl(), this); + } + + basic_symbol_iterator symbol_end_impl() const override { + DataRefImpl Symb; + Symb.p = isCode() ? 2 : 1; + return BasicSymbolRef(Symb, this); + } + +private: + bool isCode() const { + auto *Import = reinterpret_cast( + Data.getBufferStart()); + return Import->getType() == COFF::IMPORT_CODE; + } +}; + +} // namespace object +} // namespace llvm + +#endif diff --git a/lib/Object/SymbolicFile.cpp b/lib/Object/SymbolicFile.cpp index 854e68e40f4..bf79dfb8da6 100644 --- a/lib/Object/SymbolicFile.cpp +++ b/lib/Object/SymbolicFile.cpp @@ -11,6 +11,8 @@ // //===----------------------------------------------------------------------===// +#include "llvm/Object/COFF.h" +#include "llvm/Object/COFFImportFile.h" #include "llvm/Object/IRObjectFile.h" #include "llvm/Object/ObjectFile.h" #include "llvm/Object/SymbolicFile.h" @@ -54,9 +56,10 @@ ErrorOr> SymbolicFile::createSymbolicFile( case sys::fs::file_magic::macho_dynamically_linked_shared_lib_stub: case sys::fs::file_magic::macho_dsym_companion: case sys::fs::file_magic::macho_kext_bundle: - case sys::fs::file_magic::coff_import_library: case sys::fs::file_magic::pecoff_executable: return ObjectFile::createObjectFile(Object, Type); + case sys::fs::file_magic::coff_import_library: + return std::unique_ptr(new COFFImportFile(Object)); case sys::fs::file_magic::elf_relocatable: case sys::fs::file_magic::macho_object: case sys::fs::file_magic::coff_object: { diff --git a/test/Object/Inputs/coff-short-import-code b/test/Object/Inputs/coff-short-import-code new file mode 100644 index 0000000000000000000000000000000000000000..446279037b53cf0673eadfa7828e793d143b05fb GIT binary patch literal 31 mcmZQz`2U}Q!H03#$NQn&3=9m63>*ycY5DmK6?!Q-ISc@m69}*X literal 0 HcmV?d00001 diff --git a/test/Object/Inputs/coff-short-import-data b/test/Object/Inputs/coff-short-import-data new file mode 100644 index 0000000000000000000000000000000000000000..71b635ba1920a269a349864cdbd89e1ed21913d1 GIT binary patch literal 31 kcmZQz`2U}Q!H03#$NQn&3?RVC5TBG-#89D^l9R�F;9Wp#T5? literal 0 HcmV?d00001 diff --git a/test/Object/archive-symtab.test b/test/Object/archive-symtab.test index c50833d6a77..120401bad36 100644 --- a/test/Object/archive-symtab.test +++ b/test/Object/archive-symtab.test @@ -99,6 +99,16 @@ MACHO-NEXT: 0000000000000000 t _bar MACHO-NEXT: 0000000000000001 T _foo MACHO-NEXT: 0000000000000002 T _main +RUN: rm -f %t.a +RUN: llvm-ar --format=gnu rcsU %t.a %p/Inputs/coff-short-import-code %p/Inputs/coff-short-import-data +RUN: llvm-nm -M %t.a | FileCheck --check-prefix=COFF-SHORT-IMPORT %s + +COFF-SHORT-IMPORT: Archive map +COFF-SHORT-IMPORT-NEXT: _foo in coff-short-import-code +COFF-SHORT-IMPORT-NEXT: __imp__foo in coff-short-import-code +COFF-SHORT-IMPORT-NEXT: _bar in coff-short-import-data +COFF-SHORT-IMPORT-NOT: __imp__bar in coff-short-import-data + Test that we pad the symbol table so that it ends in a multiple of 4 bytes: 8 + 60 + 36 == 104 RUN: rm -f %t.a diff --git a/test/tools/llvm-readobj/file-headers.test b/test/tools/llvm-readobj/file-headers.test index fd030ef0b56..3d043f127ae 100644 --- a/test/tools/llvm-readobj/file-headers.test +++ b/test/tools/llvm-readobj/file-headers.test @@ -330,16 +330,4 @@ COFF-UNKNOWN-NEXT: Characteristics [ (0x0) COFF-UNKNOWN-NEXT: ] COFF-UNKNOWN-NEXT: } -COFF-IMPORTLIB: Format: COFF- -COFF-IMPORTLIB-NEXT: Arch: unknown -COFF-IMPORTLIB-NEXT: AddressSize: 32bit -COFF-IMPORTLIB-NEXT: ImageFileHeader { -COFF-IMPORTLIB-NEXT: Machine: IMAGE_FILE_MACHINE_UNKNOWN (0x0) -COFF-IMPORTLIB-NEXT: SectionCount: 0 -COFF-IMPORTLIB-NEXT: TimeDateStamp: 1970-09-09 19:52:32 (0x14C0000) -COFF-IMPORTLIB-NEXT: PointerToSymbolTable: 0x0 -COFF-IMPORTLIB-NEXT: SymbolCount: 0 -COFF-IMPORTLIB-NEXT: OptionalHeaderSize: 0 -COFF-IMPORTLIB-NEXT: Characteristics [ (0x0) -COFF-IMPORTLIB-NEXT: ] -COFF-IMPORTLIB-NEXT: } +COFF-IMPORTLIB: Format: COFF-import-file diff --git a/tools/llvm-readobj/llvm-readobj.cpp b/tools/llvm-readobj/llvm-readobj.cpp index d41dcc3ab4f..72844bc33a6 100644 --- a/tools/llvm-readobj/llvm-readobj.cpp +++ b/tools/llvm-readobj/llvm-readobj.cpp @@ -24,6 +24,7 @@ #include "ObjDumper.h" #include "StreamWriter.h" #include "llvm/Object/Archive.h" +#include "llvm/Object/COFFImportFile.h" #include "llvm/Object/ELFObjectFile.h" #include "llvm/Object/MachOUniversal.h" #include "llvm/Object/ObjectFile.h" @@ -330,6 +331,12 @@ static void dumpObject(const ObjectFile *Obj) { Dumper->printStackMap(); } +static void dumpCOFFImportFile(const COFFImportFile *File) { + outs() << '\n'; + outs() << "File: " << File->getFileName() << "\n"; + outs() << "Format: COFF-import-file\n"; +} + /// @brief Dumps each object file in \a Arc; static void dumpArchive(const Archive *Arc) { for (const auto &Child : Arc->children()) { @@ -384,6 +391,8 @@ static void dumpInput(StringRef File) { dumpMachOUniversalBinary(UBinary); else if (ObjectFile *Obj = dyn_cast(&Binary)) dumpObject(Obj); + else if (COFFImportFile *Import = dyn_cast(&Binary)) + dumpCOFFImportFile(Import); else reportError(File, readobj_error::unrecognized_file_format); } -- 2.34.1