1 //===- COFFObjectFile.cpp - COFF object file implementation -----*- C++ -*-===//
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 //===----------------------------------------------------------------------===//
10 // This file declares the COFFObjectFile class.
12 //===----------------------------------------------------------------------===//
14 #include "llvm/Object/COFF.h"
15 #include "llvm/ADT/StringSwitch.h"
16 #include "llvm/ADT/Triple.h"
19 using namespace object
;
22 using support::ulittle8_t
;
23 using support::ulittle16_t
;
24 using support::ulittle32_t
;
25 using support::little16_t
;
29 // Returns false if size is greater than the buffer size. And sets ec.
30 bool checkSize(const MemoryBuffer
*m
, error_code
&ec
, uint64_t size
) {
31 if (m
->getBufferSize() < size
) {
32 ec
= object_error::unexpected_eof
;
38 // Returns false if any bytes in [addr, addr + size) fall outsize of m.
39 bool checkAddr(const MemoryBuffer
*m
,
43 if (addr
+ size
< addr
||
45 addr
+ size
> uintptr_t(m
->getBufferEnd())) {
46 ec
= object_error::unexpected_eof
;
53 const coff_symbol
*COFFObjectFile::toSymb(DataRefImpl Symb
) const {
54 const coff_symbol
*addr
= reinterpret_cast<const coff_symbol
*>(Symb
.p
);
57 // Verify that the symbol points to a valid entry in the symbol table.
58 uintptr_t offset
= uintptr_t(addr
) - uintptr_t(base());
59 if (offset
< Header
->PointerToSymbolTable
60 || offset
>= Header
->PointerToSymbolTable
61 + (Header
->NumberOfSymbols
* sizeof(coff_symbol
)))
62 report_fatal_error("Symbol was outside of symbol table.");
64 assert((offset
- Header
->PointerToSymbolTable
) % sizeof(coff_symbol
)
65 == 0 && "Symbol did not point to the beginning of a symbol");
71 const coff_section
*COFFObjectFile::toSec(DataRefImpl Sec
) const {
72 const coff_section
*addr
= reinterpret_cast<const coff_section
*>(Sec
.p
);
75 // Verify that the section points to a valid entry in the section table.
76 if (addr
< SectionTable
77 || addr
>= (SectionTable
+ Header
->NumberOfSections
))
78 report_fatal_error("Section was outside of section table.");
80 uintptr_t offset
= uintptr_t(addr
) - uintptr_t(SectionTable
);
81 assert(offset
% sizeof(coff_section
) == 0 &&
82 "Section did not point to the beginning of a section");
88 error_code
COFFObjectFile::getSymbolNext(DataRefImpl Symb
,
89 SymbolRef
&Result
) const {
90 const coff_symbol
*symb
= toSymb(Symb
);
91 symb
+= 1 + symb
->NumberOfAuxSymbols
;
92 Symb
.p
= reinterpret_cast<uintptr_t>(symb
);
93 Result
= SymbolRef(Symb
, this);
94 return object_error::success
;
97 error_code
COFFObjectFile::getSymbolName(DataRefImpl Symb
,
98 StringRef
&Result
) const {
99 const coff_symbol
*symb
= toSymb(Symb
);
100 // Check for string table entry. First 4 bytes are 0.
101 if (symb
->Name
.Offset
.Zeroes
== 0) {
102 uint32_t Offset
= symb
->Name
.Offset
.Offset
;
103 if (error_code ec
= getString(Offset
, Result
))
105 return object_error::success
;
108 if (symb
->Name
.ShortName
[7] == 0)
109 // Null terminated, let ::strlen figure out the length.
110 Result
= StringRef(symb
->Name
.ShortName
);
112 // Not null terminated, use all 8 bytes.
113 Result
= StringRef(symb
->Name
.ShortName
, 8);
114 return object_error::success
;
117 error_code
COFFObjectFile::getSymbolAddress(DataRefImpl Symb
,
118 uint64_t &Result
) const {
119 const coff_symbol
*symb
= toSymb(Symb
);
120 const coff_section
*Section
= NULL
;
121 if (error_code ec
= getSection(symb
->SectionNumber
, Section
))
124 if (error_code ec
= getSymbolNMTypeChar(Symb
, Type
))
126 if (Type
== 'U' || Type
== 'w')
127 Result
= UnknownAddressOrSize
;
129 Result
= Section
->VirtualAddress
+ symb
->Value
;
131 Result
= symb
->Value
;
132 return object_error::success
;
135 error_code
COFFObjectFile::getSymbolSize(DataRefImpl Symb
,
136 uint64_t &Result
) const {
137 // FIXME: Return the correct size. This requires looking at all the symbols
138 // in the same section as this symbol, and looking for either the next
139 // symbol, or the end of the section.
140 const coff_symbol
*symb
= toSymb(Symb
);
141 const coff_section
*Section
= NULL
;
142 if (error_code ec
= getSection(symb
->SectionNumber
, Section
))
145 if (error_code ec
= getSymbolNMTypeChar(Symb
, Type
))
147 if (Type
== 'U' || Type
== 'w')
148 Result
= UnknownAddressOrSize
;
150 Result
= Section
->SizeOfRawData
- symb
->Value
;
153 return object_error::success
;
156 error_code
COFFObjectFile::getSymbolNMTypeChar(DataRefImpl Symb
,
157 char &Result
) const {
158 const coff_symbol
*symb
= toSymb(Symb
);
160 if (error_code ec
= getSymbolName(Symb
, name
))
162 char ret
= StringSwitch
<char>(name
)
163 .StartsWith(".debug", 'N')
164 .StartsWith(".sxdata", 'N')
169 return object_error::success
;
172 uint32_t Characteristics
= 0;
173 if (symb
->SectionNumber
> 0) {
174 const coff_section
*Section
= NULL
;
175 if (error_code ec
= getSection(symb
->SectionNumber
, Section
))
177 Characteristics
= Section
->Characteristics
;
180 switch (symb
->SectionNumber
) {
181 case COFF::IMAGE_SYM_UNDEFINED
:
182 // Check storage classes.
183 if (symb
->StorageClass
== COFF::IMAGE_SYM_CLASS_WEAK_EXTERNAL
) {
185 return object_error::success
; // Don't do ::toupper.
189 case COFF::IMAGE_SYM_ABSOLUTE
:
192 case COFF::IMAGE_SYM_DEBUG
:
196 // Check section type.
197 if (Characteristics
& COFF::IMAGE_SCN_CNT_CODE
)
199 else if ( Characteristics
& COFF::IMAGE_SCN_MEM_READ
200 && ~Characteristics
& COFF::IMAGE_SCN_MEM_WRITE
) // Read only.
202 else if (Characteristics
& COFF::IMAGE_SCN_CNT_INITIALIZED_DATA
)
204 else if (Characteristics
& COFF::IMAGE_SCN_CNT_UNINITIALIZED_DATA
)
206 else if (Characteristics
& COFF::IMAGE_SCN_LNK_INFO
)
209 // Check for section symbol.
210 else if ( symb
->StorageClass
== COFF::IMAGE_SYM_CLASS_STATIC
215 if (symb
->StorageClass
== COFF::IMAGE_SYM_CLASS_EXTERNAL
)
216 ret
= ::toupper(ret
);
219 return object_error::success
;
222 error_code
COFFObjectFile::isSymbolInternal(DataRefImpl Symb
,
223 bool &Result
) const {
225 return object_error::success
;
228 error_code
COFFObjectFile::getSectionNext(DataRefImpl Sec
,
229 SectionRef
&Result
) const {
230 const coff_section
*sec
= toSec(Sec
);
232 Sec
.p
= reinterpret_cast<uintptr_t>(sec
);
233 Result
= SectionRef(Sec
, this);
234 return object_error::success
;
237 error_code
COFFObjectFile::getSectionName(DataRefImpl Sec
,
238 StringRef
&Result
) const {
239 const coff_section
*sec
= toSec(Sec
);
241 if (sec
->Name
[7] == 0)
242 // Null terminated, let ::strlen figure out the length.
245 // Not null terminated, use all 8 bytes.
246 name
= StringRef(sec
->Name
, 8);
248 // Check for string table entry. First byte is '/'.
249 if (name
[0] == '/') {
251 name
.substr(1).getAsInteger(10, Offset
);
252 if (error_code ec
= getString(Offset
, name
))
257 return object_error::success
;
260 error_code
COFFObjectFile::getSectionAddress(DataRefImpl Sec
,
261 uint64_t &Result
) const {
262 const coff_section
*sec
= toSec(Sec
);
263 Result
= sec
->VirtualAddress
;
264 return object_error::success
;
267 error_code
COFFObjectFile::getSectionSize(DataRefImpl Sec
,
268 uint64_t &Result
) const {
269 const coff_section
*sec
= toSec(Sec
);
270 Result
= sec
->SizeOfRawData
;
271 return object_error::success
;
274 error_code
COFFObjectFile::getSectionContents(DataRefImpl Sec
,
275 StringRef
&Result
) const {
276 const coff_section
*sec
= toSec(Sec
);
277 // The only thing that we need to verify is that the contents is contained
278 // within the file bounds. We don't need to make sure it doesn't cover other
279 // data, as there's nothing that says that is not allowed.
280 uintptr_t con_start
= uintptr_t(base()) + sec
->PointerToRawData
;
281 uintptr_t con_end
= con_start
+ sec
->SizeOfRawData
;
282 if (con_end
>= uintptr_t(Data
->getBufferEnd()))
283 return object_error::parse_failed
;
284 Result
= StringRef(reinterpret_cast<const char*>(con_start
),
286 return object_error::success
;
289 error_code
COFFObjectFile::isSectionText(DataRefImpl Sec
,
290 bool &Result
) const {
291 const coff_section
*sec
= toSec(Sec
);
292 Result
= sec
->Characteristics
& COFF::IMAGE_SCN_CNT_CODE
;
293 return object_error::success
;
296 COFFObjectFile::COFFObjectFile(MemoryBuffer
*Object
, error_code
&ec
)
297 : ObjectFile(Binary::isCOFF
, Object
, ec
) {
298 // Check that we at least have enough room for a header.
299 if (!checkSize(Data
, ec
, sizeof(coff_file_header
))) return;
301 // The actual starting location of the COFF header in the file. This can be
302 // non-zero in PE/COFF files.
303 uint64_t HeaderStart
= 0;
305 // Check if this is a PE/COFF file.
306 if (base()[0] == 0x4d && base()[1] == 0x5a) {
307 // PE/COFF, seek through MS-DOS compatibility stub and 4-byte
308 // PE signature to find 'normal' COFF header.
309 if (!checkSize(Data
, ec
, 0x3c + 8)) return;
310 HeaderStart
+= *reinterpret_cast<const ulittle32_t
*>(base() + 0x3c);
311 // Check the PE header. ("PE\0\0")
312 if (std::memcmp(base() + HeaderStart
, "PE\0\0", 4) != 0) {
313 ec
= object_error::parse_failed
;
316 HeaderStart
+= 4; // Skip the PE Header.
319 Header
= reinterpret_cast<const coff_file_header
*>(base() + HeaderStart
);
320 if (!checkAddr(Data
, ec
, uintptr_t(Header
), sizeof(coff_file_header
)))
324 reinterpret_cast<const coff_section
*>( base()
326 + sizeof(coff_file_header
)
327 + Header
->SizeOfOptionalHeader
);
328 if (!checkAddr(Data
, ec
, uintptr_t(SectionTable
),
329 Header
->NumberOfSections
* sizeof(coff_section
)))
333 reinterpret_cast<const coff_symbol
*>(base()
334 + Header
->PointerToSymbolTable
);
335 if (!checkAddr(Data
, ec
, uintptr_t(SymbolTable
),
336 Header
->NumberOfSymbols
* sizeof(coff_symbol
)))
339 // Find string table.
340 StringTable
= reinterpret_cast<const char *>(base())
341 + Header
->PointerToSymbolTable
342 + Header
->NumberOfSymbols
* sizeof(coff_symbol
);
343 if (!checkAddr(Data
, ec
, uintptr_t(StringTable
), sizeof(ulittle32_t
)))
346 StringTableSize
= *reinterpret_cast<const ulittle32_t
*>(StringTable
);
347 if (!checkAddr(Data
, ec
, uintptr_t(StringTable
), StringTableSize
))
349 // Check that the string table is null terminated if has any in it.
350 if (StringTableSize
< 4
351 || (StringTableSize
> 4 && StringTable
[StringTableSize
- 1] != 0)) {
352 ec
= object_error::parse_failed
;
356 ec
= object_error::success
;
359 ObjectFile::symbol_iterator
COFFObjectFile::begin_symbols() const {
361 std::memset(&ret
, 0, sizeof(DataRefImpl
));
362 ret
.p
= reinterpret_cast<intptr_t>(SymbolTable
);
363 return symbol_iterator(SymbolRef(ret
, this));
366 ObjectFile::symbol_iterator
COFFObjectFile::end_symbols() const {
367 // The symbol table ends where the string table begins.
369 std::memset(&ret
, 0, sizeof(DataRefImpl
));
370 ret
.p
= reinterpret_cast<intptr_t>(StringTable
);
371 return symbol_iterator(SymbolRef(ret
, this));
374 ObjectFile::section_iterator
COFFObjectFile::begin_sections() const {
376 std::memset(&ret
, 0, sizeof(DataRefImpl
));
377 ret
.p
= reinterpret_cast<intptr_t>(SectionTable
);
378 return section_iterator(SectionRef(ret
, this));
381 ObjectFile::section_iterator
COFFObjectFile::end_sections() const {
383 std::memset(&ret
, 0, sizeof(DataRefImpl
));
384 ret
.p
= reinterpret_cast<intptr_t>(SectionTable
+ Header
->NumberOfSections
);
385 return section_iterator(SectionRef(ret
, this));
388 uint8_t COFFObjectFile::getBytesInAddress() const {
389 return getArch() == Triple::x86_64
? 8 : 4;
392 StringRef
COFFObjectFile::getFileFormatName() const {
393 switch(Header
->Machine
) {
394 case COFF::IMAGE_FILE_MACHINE_I386
:
396 case COFF::IMAGE_FILE_MACHINE_AMD64
:
397 return "COFF-x86-64";
399 return "COFF-<unknown arch>";
403 unsigned COFFObjectFile::getArch() const {
404 switch(Header
->Machine
) {
405 case COFF::IMAGE_FILE_MACHINE_I386
:
407 case COFF::IMAGE_FILE_MACHINE_AMD64
:
408 return Triple::x86_64
;
410 return Triple::UnknownArch
;
414 error_code
COFFObjectFile::getSection(int32_t index
,
415 const coff_section
*&Result
) const {
416 // Check for special index values.
417 if (index
== COFF::IMAGE_SYM_UNDEFINED
||
418 index
== COFF::IMAGE_SYM_ABSOLUTE
||
419 index
== COFF::IMAGE_SYM_DEBUG
)
421 else if (index
> 0 && index
<= Header
->NumberOfSections
)
422 // We already verified the section table data, so no need to check again.
423 Result
= SectionTable
+ (index
- 1);
425 return object_error::parse_failed
;
426 return object_error::success
;
429 error_code
COFFObjectFile::getString(uint32_t offset
,
430 StringRef
&Result
) const {
431 if (StringTableSize
<= 4)
432 // Tried to get a string from an empty string table.
433 return object_error::parse_failed
;
434 if (offset
>= StringTableSize
)
435 return object_error::unexpected_eof
;
436 Result
= StringRef(StringTable
+ offset
);
437 return object_error::success
;
442 ObjectFile
*ObjectFile::createCOFFObjectFile(MemoryBuffer
*Object
) {
444 return new COFFObjectFile(Object
, ec
);
447 } // end namespace llvm