1 //===- Reader.cpp ---------------------------------------------------------===//
3 // The LLVM Compiler Infrastructure
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
8 //===----------------------------------------------------------------------===//
12 #include "llvm-objcopy.h"
13 #include "llvm/ADT/ArrayRef.h"
14 #include "llvm/ADT/StringRef.h"
15 #include "llvm/Object/COFF.h"
16 #include "llvm/Support/ErrorHandling.h"
24 using namespace object
;
28 Error
COFFReader::readExecutableHeaders(Object
&Obj
) const {
29 const dos_header
*DH
= COFFObj
.getDOSHeader();
30 Obj
.Is64
= COFFObj
.is64();
32 return Error::success();
36 if (DH
->AddressOfNewExeHeader
> sizeof(*DH
))
37 Obj
.DosStub
= ArrayRef
<uint8_t>(reinterpret_cast<const uint8_t *>(&DH
[1]),
38 DH
->AddressOfNewExeHeader
- sizeof(*DH
));
41 const pe32plus_header
*PE32Plus
= nullptr;
42 if (auto EC
= COFFObj
.getPE32PlusHeader(PE32Plus
))
43 return errorCodeToError(EC
);
44 Obj
.PeHeader
= *PE32Plus
;
46 const pe32_header
*PE32
= nullptr;
47 if (auto EC
= COFFObj
.getPE32Header(PE32
))
48 return errorCodeToError(EC
);
49 copyPeHeader(Obj
.PeHeader
, *PE32
);
50 // The pe32plus_header (stored in Object) lacks the BaseOfData field.
51 Obj
.BaseOfData
= PE32
->BaseOfData
;
54 for (size_t I
= 0; I
< Obj
.PeHeader
.NumberOfRvaAndSize
; I
++) {
55 const data_directory
*Dir
;
56 if (auto EC
= COFFObj
.getDataDirectory(I
, Dir
))
57 return errorCodeToError(EC
);
58 Obj
.DataDirectories
.emplace_back(*Dir
);
60 return Error::success();
63 Error
COFFReader::readSections(Object
&Obj
) const {
64 // Section indexing starts from 1.
65 for (size_t I
= 1, E
= COFFObj
.getNumberOfSections(); I
<= E
; I
++) {
66 const coff_section
*Sec
;
67 if (auto EC
= COFFObj
.getSection(I
, Sec
))
68 return errorCodeToError(EC
);
69 Obj
.Sections
.push_back(Section());
70 Section
&S
= Obj
.Sections
.back();
72 if (auto EC
= COFFObj
.getSectionContents(Sec
, S
.Contents
))
73 return errorCodeToError(EC
);
74 ArrayRef
<coff_relocation
> Relocs
= COFFObj
.getRelocations(Sec
);
75 for (const coff_relocation
&R
: Relocs
)
76 S
.Relocs
.push_back(R
);
77 if (auto EC
= COFFObj
.getSectionName(Sec
, S
.Name
))
78 return errorCodeToError(EC
);
79 if (Sec
->hasExtendedRelocations())
80 return make_error
<StringError
>("Extended relocations not supported yet",
81 object_error::parse_failed
);
83 return Error::success();
86 Error
COFFReader::readSymbols(Object
&Obj
, bool IsBigObj
) const {
87 std::vector
<Symbol
> Symbols
;
88 Symbols
.reserve(COFFObj
.getRawNumberOfSymbols());
89 for (uint32_t I
= 0, E
= COFFObj
.getRawNumberOfSymbols(); I
< E
;) {
90 Expected
<COFFSymbolRef
> SymOrErr
= COFFObj
.getSymbol(I
);
92 return SymOrErr
.takeError();
93 COFFSymbolRef SymRef
= *SymOrErr
;
95 Symbols
.push_back(Symbol());
96 Symbol
&Sym
= Symbols
.back();
97 // Copy symbols from the original form into an intermediate coff_symbol32.
100 *reinterpret_cast<const coff_symbol32
*>(SymRef
.getRawPtr()));
103 *reinterpret_cast<const coff_symbol16
*>(SymRef
.getRawPtr()));
104 if (auto EC
= COFFObj
.getSymbolName(SymRef
, Sym
.Name
))
105 return errorCodeToError(EC
);
106 Sym
.AuxData
= COFFObj
.getSymbolAuxData(SymRef
);
107 assert((Sym
.AuxData
.size() %
108 (IsBigObj
? sizeof(coff_symbol32
) : sizeof(coff_symbol16
))) == 0);
109 I
+= 1 + SymRef
.getNumberOfAuxSymbols();
111 Obj
.addSymbols(Symbols
);
112 return Error::success();
115 Error
COFFReader::setRelocTargets(Object
&Obj
) const {
116 std::vector
<const Symbol
*> RawSymbolTable
;
117 for (const Symbol
&Sym
: Obj
.getSymbols()) {
118 RawSymbolTable
.push_back(&Sym
);
119 for (size_t I
= 0; I
< Sym
.Sym
.NumberOfAuxSymbols
; I
++)
120 RawSymbolTable
.push_back(nullptr);
122 for (Section
&Sec
: Obj
.Sections
) {
123 for (Relocation
&R
: Sec
.Relocs
) {
124 if (R
.Reloc
.SymbolTableIndex
>= RawSymbolTable
.size())
125 return make_error
<StringError
>("SymbolTableIndex out of range",
126 object_error::parse_failed
);
127 const Symbol
*Sym
= RawSymbolTable
[R
.Reloc
.SymbolTableIndex
];
129 return make_error
<StringError
>("Invalid SymbolTableIndex",
130 object_error::parse_failed
);
131 R
.Target
= Sym
->UniqueId
;
132 R
.TargetName
= Sym
->Name
;
135 return Error::success();
138 Expected
<std::unique_ptr
<Object
>> COFFReader::create() const {
139 auto Obj
= llvm::make_unique
<Object
>();
141 const coff_file_header
*CFH
= nullptr;
142 const coff_bigobj_file_header
*CBFH
= nullptr;
143 COFFObj
.getCOFFHeader(CFH
);
144 COFFObj
.getCOFFBigObjHeader(CBFH
);
145 bool IsBigObj
= false;
147 Obj
->CoffFileHeader
= *CFH
;
150 return make_error
<StringError
>("No COFF file header returned",
151 object_error::parse_failed
);
152 // Only copying the few fields from the bigobj header that we need
153 // and won't recreate in the end.
154 Obj
->CoffFileHeader
.Machine
= CBFH
->Machine
;
155 Obj
->CoffFileHeader
.TimeDateStamp
= CBFH
->TimeDateStamp
;
159 if (Error E
= readExecutableHeaders(*Obj
))
161 if (Error E
= readSections(*Obj
))
163 if (Error E
= readSymbols(*Obj
, IsBigObj
))
165 if (Error E
= setRelocTargets(*Obj
))
168 return std::move(Obj
);
171 } // end namespace coff
172 } // end namespace objcopy
173 } // end namespace llvm