COFFObjectFile.cpp revision 13afc5eff2d7370ab486d5039886ab8bbf9039da
1a1ef8ef66075e28e020e5d2f408e0a9bae9eb9d3Michael J. Spencer//===- COFFObjectFile.cpp - COFF object file implementation -----*- C++ -*-===//
2a1ef8ef66075e28e020e5d2f408e0a9bae9eb9d3Michael J. Spencer//
3a1ef8ef66075e28e020e5d2f408e0a9bae9eb9d3Michael J. Spencer//                     The LLVM Compiler Infrastructure
4a1ef8ef66075e28e020e5d2f408e0a9bae9eb9d3Michael J. Spencer//
5a1ef8ef66075e28e020e5d2f408e0a9bae9eb9d3Michael J. Spencer// This file is distributed under the University of Illinois Open Source
6a1ef8ef66075e28e020e5d2f408e0a9bae9eb9d3Michael J. Spencer// License. See LICENSE.TXT for details.
7a1ef8ef66075e28e020e5d2f408e0a9bae9eb9d3Michael J. Spencer//
8a1ef8ef66075e28e020e5d2f408e0a9bae9eb9d3Michael J. Spencer//===----------------------------------------------------------------------===//
9a1ef8ef66075e28e020e5d2f408e0a9bae9eb9d3Michael J. Spencer//
10a1ef8ef66075e28e020e5d2f408e0a9bae9eb9d3Michael J. Spencer// This file declares the COFFObjectFile class.
11a1ef8ef66075e28e020e5d2f408e0a9bae9eb9d3Michael J. Spencer//
12a1ef8ef66075e28e020e5d2f408e0a9bae9eb9d3Michael J. Spencer//===----------------------------------------------------------------------===//
13a1ef8ef66075e28e020e5d2f408e0a9bae9eb9d3Michael J. Spencer
14001c9205fca2220480589ec355cb6ec701a37e08Michael J. Spencer#include "llvm/Object/COFF.h"
15a1ef8ef66075e28e020e5d2f408e0a9bae9eb9d3Michael J. Spencer#include "llvm/ADT/StringSwitch.h"
16a1ef8ef66075e28e020e5d2f408e0a9bae9eb9d3Michael J. Spencer#include "llvm/ADT/Triple.h"
17a1ef8ef66075e28e020e5d2f408e0a9bae9eb9d3Michael J. Spencer
18a1ef8ef66075e28e020e5d2f408e0a9bae9eb9d3Michael J. Spencerusing namespace llvm;
19a1ef8ef66075e28e020e5d2f408e0a9bae9eb9d3Michael J. Spencerusing namespace object;
20a1ef8ef66075e28e020e5d2f408e0a9bae9eb9d3Michael J. Spencer
21a1ef8ef66075e28e020e5d2f408e0a9bae9eb9d3Michael J. Spencernamespace {
22a1ef8ef66075e28e020e5d2f408e0a9bae9eb9d3Michael J. Spencerusing support::ulittle8_t;
23a1ef8ef66075e28e020e5d2f408e0a9bae9eb9d3Michael J. Spencerusing support::ulittle16_t;
24a1ef8ef66075e28e020e5d2f408e0a9bae9eb9d3Michael J. Spencerusing support::ulittle32_t;
25a1ef8ef66075e28e020e5d2f408e0a9bae9eb9d3Michael J. Spencerusing support::little16_t;
26a1ef8ef66075e28e020e5d2f408e0a9bae9eb9d3Michael J. Spencer}
27a1ef8ef66075e28e020e5d2f408e0a9bae9eb9d3Michael J. Spencer
2825b15777df42d5d608810f6881b6c98107481d69Michael J. Spencernamespace {
2925b15777df42d5d608810f6881b6c98107481d69Michael J. Spencer// Returns false if size is greater than the buffer size. And sets ec.
3025b15777df42d5d608810f6881b6c98107481d69Michael J. Spencerbool checkSize(const MemoryBuffer *m, error_code &ec, uint64_t size) {
3125b15777df42d5d608810f6881b6c98107481d69Michael J. Spencer  if (m->getBufferSize() < size) {
3225b15777df42d5d608810f6881b6c98107481d69Michael J. Spencer    ec = object_error::unexpected_eof;
3325b15777df42d5d608810f6881b6c98107481d69Michael J. Spencer    return false;
3425b15777df42d5d608810f6881b6c98107481d69Michael J. Spencer  }
3525b15777df42d5d608810f6881b6c98107481d69Michael J. Spencer  return true;
3625b15777df42d5d608810f6881b6c98107481d69Michael J. Spencer}
3725b15777df42d5d608810f6881b6c98107481d69Michael J. Spencer
3825b15777df42d5d608810f6881b6c98107481d69Michael J. Spencer// Returns false if any bytes in [addr, addr + size) fall outsize of m.
3925b15777df42d5d608810f6881b6c98107481d69Michael J. Spencerbool checkAddr(const MemoryBuffer *m,
4025b15777df42d5d608810f6881b6c98107481d69Michael J. Spencer               error_code &ec,
4125b15777df42d5d608810f6881b6c98107481d69Michael J. Spencer               uintptr_t addr,
4225b15777df42d5d608810f6881b6c98107481d69Michael J. Spencer               uint64_t size) {
4325b15777df42d5d608810f6881b6c98107481d69Michael J. Spencer  if (addr + size < addr ||
4425b15777df42d5d608810f6881b6c98107481d69Michael J. Spencer      addr + size < size ||
4525b15777df42d5d608810f6881b6c98107481d69Michael J. Spencer      addr + size > uintptr_t(m->getBufferEnd())) {
4625b15777df42d5d608810f6881b6c98107481d69Michael J. Spencer    ec = object_error::unexpected_eof;
4725b15777df42d5d608810f6881b6c98107481d69Michael J. Spencer    return false;
4825b15777df42d5d608810f6881b6c98107481d69Michael J. Spencer  }
4925b15777df42d5d608810f6881b6c98107481d69Michael J. Spencer  return true;
5025b15777df42d5d608810f6881b6c98107481d69Michael J. Spencer}
5125b15777df42d5d608810f6881b6c98107481d69Michael J. Spencer}
5225b15777df42d5d608810f6881b6c98107481d69Michael J. Spencer
5325b15777df42d5d608810f6881b6c98107481d69Michael J. Spencerconst coff_symbol *COFFObjectFile::toSymb(DataRefImpl Symb) const {
5425b15777df42d5d608810f6881b6c98107481d69Michael J. Spencer  const coff_symbol *addr = reinterpret_cast<const coff_symbol*>(Symb.p);
5525b15777df42d5d608810f6881b6c98107481d69Michael J. Spencer
5625b15777df42d5d608810f6881b6c98107481d69Michael J. Spencer# ifndef NDEBUG
5725b15777df42d5d608810f6881b6c98107481d69Michael J. Spencer  // Verify that the symbol points to a valid entry in the symbol table.
5825b15777df42d5d608810f6881b6c98107481d69Michael J. Spencer  uintptr_t offset = uintptr_t(addr) - uintptr_t(base());
5925b15777df42d5d608810f6881b6c98107481d69Michael J. Spencer  if (offset < Header->PointerToSymbolTable
6025b15777df42d5d608810f6881b6c98107481d69Michael J. Spencer      || offset >= Header->PointerToSymbolTable
6125b15777df42d5d608810f6881b6c98107481d69Michael J. Spencer         + (Header->NumberOfSymbols * sizeof(coff_symbol)))
6225b15777df42d5d608810f6881b6c98107481d69Michael J. Spencer    report_fatal_error("Symbol was outside of symbol table.");
6325b15777df42d5d608810f6881b6c98107481d69Michael J. Spencer
6425b15777df42d5d608810f6881b6c98107481d69Michael J. Spencer  assert((offset - Header->PointerToSymbolTable) % sizeof(coff_symbol)
6525b15777df42d5d608810f6881b6c98107481d69Michael J. Spencer         == 0 && "Symbol did not point to the beginning of a symbol");
6625b15777df42d5d608810f6881b6c98107481d69Michael J. Spencer# endif
6725b15777df42d5d608810f6881b6c98107481d69Michael J. Spencer
6825b15777df42d5d608810f6881b6c98107481d69Michael J. Spencer  return addr;
6925b15777df42d5d608810f6881b6c98107481d69Michael J. Spencer}
7025b15777df42d5d608810f6881b6c98107481d69Michael J. Spencer
7125b15777df42d5d608810f6881b6c98107481d69Michael J. Spencerconst coff_section *COFFObjectFile::toSec(DataRefImpl Sec) const {
7225b15777df42d5d608810f6881b6c98107481d69Michael J. Spencer  const coff_section *addr = reinterpret_cast<const coff_section*>(Sec.p);
7325b15777df42d5d608810f6881b6c98107481d69Michael J. Spencer
7425b15777df42d5d608810f6881b6c98107481d69Michael J. Spencer# ifndef NDEBUG
7525b15777df42d5d608810f6881b6c98107481d69Michael J. Spencer  // Verify that the section points to a valid entry in the section table.
7625b15777df42d5d608810f6881b6c98107481d69Michael J. Spencer  if (addr < SectionTable
7725b15777df42d5d608810f6881b6c98107481d69Michael J. Spencer      || addr >= (SectionTable + Header->NumberOfSections))
7825b15777df42d5d608810f6881b6c98107481d69Michael J. Spencer    report_fatal_error("Section was outside of section table.");
7925b15777df42d5d608810f6881b6c98107481d69Michael J. Spencer
8025b15777df42d5d608810f6881b6c98107481d69Michael J. Spencer  uintptr_t offset = uintptr_t(addr) - uintptr_t(SectionTable);
8125b15777df42d5d608810f6881b6c98107481d69Michael J. Spencer  assert(offset % sizeof(coff_section) == 0 &&
8225b15777df42d5d608810f6881b6c98107481d69Michael J. Spencer         "Section did not point to the beginning of a section");
8325b15777df42d5d608810f6881b6c98107481d69Michael J. Spencer# endif
8425b15777df42d5d608810f6881b6c98107481d69Michael J. Spencer
8525b15777df42d5d608810f6881b6c98107481d69Michael J. Spencer  return addr;
8625b15777df42d5d608810f6881b6c98107481d69Michael J. Spencer}
8725b15777df42d5d608810f6881b6c98107481d69Michael J. Spencer
8825b15777df42d5d608810f6881b6c98107481d69Michael J. Spencererror_code COFFObjectFile::getSymbolNext(DataRefImpl Symb,
8925b15777df42d5d608810f6881b6c98107481d69Michael J. Spencer                                         SymbolRef &Result) const {
9025b15777df42d5d608810f6881b6c98107481d69Michael J. Spencer  const coff_symbol *symb = toSymb(Symb);
91a1ef8ef66075e28e020e5d2f408e0a9bae9eb9d3Michael J. Spencer  symb += 1 + symb->NumberOfAuxSymbols;
9225b15777df42d5d608810f6881b6c98107481d69Michael J. Spencer  Symb.p = reinterpret_cast<uintptr_t>(symb);
9325b15777df42d5d608810f6881b6c98107481d69Michael J. Spencer  Result = SymbolRef(Symb, this);
9425b15777df42d5d608810f6881b6c98107481d69Michael J. Spencer  return object_error::success;
95a1ef8ef66075e28e020e5d2f408e0a9bae9eb9d3Michael J. Spencer}
96a1ef8ef66075e28e020e5d2f408e0a9bae9eb9d3Michael J. Spencer
9725b15777df42d5d608810f6881b6c98107481d69Michael J. Spencer error_code COFFObjectFile::getSymbolName(DataRefImpl Symb,
9825b15777df42d5d608810f6881b6c98107481d69Michael J. Spencer                                          StringRef &Result) const {
9925b15777df42d5d608810f6881b6c98107481d69Michael J. Spencer  const coff_symbol *symb = toSymb(Symb);
100a1ef8ef66075e28e020e5d2f408e0a9bae9eb9d3Michael J. Spencer  // Check for string table entry. First 4 bytes are 0.
101a1ef8ef66075e28e020e5d2f408e0a9bae9eb9d3Michael J. Spencer  if (symb->Name.Offset.Zeroes == 0) {
102a1ef8ef66075e28e020e5d2f408e0a9bae9eb9d3Michael J. Spencer    uint32_t Offset = symb->Name.Offset.Offset;
10325b15777df42d5d608810f6881b6c98107481d69Michael J. Spencer    if (error_code ec = getString(Offset, Result))
10425b15777df42d5d608810f6881b6c98107481d69Michael J. Spencer      return ec;
10525b15777df42d5d608810f6881b6c98107481d69Michael J. Spencer    return object_error::success;
106a1ef8ef66075e28e020e5d2f408e0a9bae9eb9d3Michael J. Spencer  }
107a1ef8ef66075e28e020e5d2f408e0a9bae9eb9d3Michael J. Spencer
108a1ef8ef66075e28e020e5d2f408e0a9bae9eb9d3Michael J. Spencer  if (symb->Name.ShortName[7] == 0)
109a1ef8ef66075e28e020e5d2f408e0a9bae9eb9d3Michael J. Spencer    // Null terminated, let ::strlen figure out the length.
11025b15777df42d5d608810f6881b6c98107481d69Michael J. Spencer    Result = StringRef(symb->Name.ShortName);
11125b15777df42d5d608810f6881b6c98107481d69Michael J. Spencer  else
11225b15777df42d5d608810f6881b6c98107481d69Michael J. Spencer    // Not null terminated, use all 8 bytes.
11325b15777df42d5d608810f6881b6c98107481d69Michael J. Spencer    Result = StringRef(symb->Name.ShortName, 8);
11425b15777df42d5d608810f6881b6c98107481d69Michael J. Spencer  return object_error::success;
115a1ef8ef66075e28e020e5d2f408e0a9bae9eb9d3Michael J. Spencer}
116a1ef8ef66075e28e020e5d2f408e0a9bae9eb9d3Michael J. Spencer
117ac241fe9f0d73c6f632e4f7f89e06b698d39da54Benjamin Kramererror_code COFFObjectFile::getSymbolOffset(DataRefImpl Symb,
11825b15777df42d5d608810f6881b6c98107481d69Michael J. Spencer                                            uint64_t &Result) const {
11925b15777df42d5d608810f6881b6c98107481d69Michael J. Spencer  const coff_symbol *symb = toSymb(Symb);
12064388ceee00d5e8fc8750ce7967c07a83af3a5a8Michael J. Spencer  const coff_section *Section = NULL;
12125b15777df42d5d608810f6881b6c98107481d69Michael J. Spencer  if (error_code ec = getSection(symb->SectionNumber, Section))
12225b15777df42d5d608810f6881b6c98107481d69Michael J. Spencer    return ec;
12325b15777df42d5d608810f6881b6c98107481d69Michael J. Spencer  char Type;
12425b15777df42d5d608810f6881b6c98107481d69Michael J. Spencer  if (error_code ec = getSymbolNMTypeChar(Symb, Type))
12525b15777df42d5d608810f6881b6c98107481d69Michael J. Spencer    return ec;
126a1ef8ef66075e28e020e5d2f408e0a9bae9eb9d3Michael J. Spencer  if (Type == 'U' || Type == 'w')
12725b15777df42d5d608810f6881b6c98107481d69Michael J. Spencer    Result = UnknownAddressOrSize;
12825b15777df42d5d608810f6881b6c98107481d69Michael J. Spencer  else if (Section)
12925b15777df42d5d608810f6881b6c98107481d69Michael J. Spencer    Result = Section->VirtualAddress + symb->Value;
13025b15777df42d5d608810f6881b6c98107481d69Michael J. Spencer  else
13125b15777df42d5d608810f6881b6c98107481d69Michael J. Spencer    Result = symb->Value;
13225b15777df42d5d608810f6881b6c98107481d69Michael J. Spencer  return object_error::success;
133a1ef8ef66075e28e020e5d2f408e0a9bae9eb9d3Michael J. Spencer}
134a1ef8ef66075e28e020e5d2f408e0a9bae9eb9d3Michael J. Spencer
135ac241fe9f0d73c6f632e4f7f89e06b698d39da54Benjamin Kramererror_code COFFObjectFile::getSymbolAddress(DataRefImpl Symb,
136ac241fe9f0d73c6f632e4f7f89e06b698d39da54Benjamin Kramer                                            uint64_t &Result) const {
137ac241fe9f0d73c6f632e4f7f89e06b698d39da54Benjamin Kramer  const coff_symbol *symb = toSymb(Symb);
138ac241fe9f0d73c6f632e4f7f89e06b698d39da54Benjamin Kramer  const coff_section *Section = NULL;
139ac241fe9f0d73c6f632e4f7f89e06b698d39da54Benjamin Kramer  if (error_code ec = getSection(symb->SectionNumber, Section))
140ac241fe9f0d73c6f632e4f7f89e06b698d39da54Benjamin Kramer    return ec;
141ac241fe9f0d73c6f632e4f7f89e06b698d39da54Benjamin Kramer  char Type;
142ac241fe9f0d73c6f632e4f7f89e06b698d39da54Benjamin Kramer  if (error_code ec = getSymbolNMTypeChar(Symb, Type))
143ac241fe9f0d73c6f632e4f7f89e06b698d39da54Benjamin Kramer    return ec;
144ac241fe9f0d73c6f632e4f7f89e06b698d39da54Benjamin Kramer  if (Type == 'U' || Type == 'w')
145ac241fe9f0d73c6f632e4f7f89e06b698d39da54Benjamin Kramer    Result = UnknownAddressOrSize;
146ac241fe9f0d73c6f632e4f7f89e06b698d39da54Benjamin Kramer  else if (Section)
147ac241fe9f0d73c6f632e4f7f89e06b698d39da54Benjamin Kramer    Result = reinterpret_cast<uintptr_t>(base() +
148ac241fe9f0d73c6f632e4f7f89e06b698d39da54Benjamin Kramer                                         Section->PointerToRawData +
149ac241fe9f0d73c6f632e4f7f89e06b698d39da54Benjamin Kramer                                         symb->Value);
150ac241fe9f0d73c6f632e4f7f89e06b698d39da54Benjamin Kramer  else
151ac241fe9f0d73c6f632e4f7f89e06b698d39da54Benjamin Kramer    Result = reinterpret_cast<uintptr_t>(base() + symb->Value);
152ac241fe9f0d73c6f632e4f7f89e06b698d39da54Benjamin Kramer  return object_error::success;
153ac241fe9f0d73c6f632e4f7f89e06b698d39da54Benjamin Kramer}
154ac241fe9f0d73c6f632e4f7f89e06b698d39da54Benjamin Kramer
155ac241fe9f0d73c6f632e4f7f89e06b698d39da54Benjamin Kramererror_code COFFObjectFile::getSymbolType(DataRefImpl Symb,
156ac241fe9f0d73c6f632e4f7f89e06b698d39da54Benjamin Kramer                                         SymbolRef::SymbolType &Result) const {
157ac241fe9f0d73c6f632e4f7f89e06b698d39da54Benjamin Kramer  const coff_symbol *symb = toSymb(Symb);
158ac241fe9f0d73c6f632e4f7f89e06b698d39da54Benjamin Kramer  Result = SymbolRef::ST_Other;
159ac241fe9f0d73c6f632e4f7f89e06b698d39da54Benjamin Kramer  if (symb->StorageClass == COFF::IMAGE_SYM_CLASS_EXTERNAL &&
160ac241fe9f0d73c6f632e4f7f89e06b698d39da54Benjamin Kramer      symb->SectionNumber == COFF::IMAGE_SYM_UNDEFINED) {
161ac241fe9f0d73c6f632e4f7f89e06b698d39da54Benjamin Kramer    Result = SymbolRef::ST_External;
162ac241fe9f0d73c6f632e4f7f89e06b698d39da54Benjamin Kramer  } else {
163ac241fe9f0d73c6f632e4f7f89e06b698d39da54Benjamin Kramer    if (symb->Type.ComplexType == COFF::IMAGE_SYM_DTYPE_FUNCTION) {
164ac241fe9f0d73c6f632e4f7f89e06b698d39da54Benjamin Kramer      Result = SymbolRef::ST_Function;
165ac241fe9f0d73c6f632e4f7f89e06b698d39da54Benjamin Kramer    } else {
166ac241fe9f0d73c6f632e4f7f89e06b698d39da54Benjamin Kramer      char Type;
167ac241fe9f0d73c6f632e4f7f89e06b698d39da54Benjamin Kramer      if (error_code ec = getSymbolNMTypeChar(Symb, Type))
168ac241fe9f0d73c6f632e4f7f89e06b698d39da54Benjamin Kramer        return ec;
169ac241fe9f0d73c6f632e4f7f89e06b698d39da54Benjamin Kramer      if (Type == 'r' || Type == 'R') {
170ac241fe9f0d73c6f632e4f7f89e06b698d39da54Benjamin Kramer        Result = SymbolRef::ST_Data;
171ac241fe9f0d73c6f632e4f7f89e06b698d39da54Benjamin Kramer      }
172ac241fe9f0d73c6f632e4f7f89e06b698d39da54Benjamin Kramer    }
173ac241fe9f0d73c6f632e4f7f89e06b698d39da54Benjamin Kramer  }
174ac241fe9f0d73c6f632e4f7f89e06b698d39da54Benjamin Kramer  return object_error::success;
175ac241fe9f0d73c6f632e4f7f89e06b698d39da54Benjamin Kramer}
176ac241fe9f0d73c6f632e4f7f89e06b698d39da54Benjamin Kramer
177ac241fe9f0d73c6f632e4f7f89e06b698d39da54Benjamin Kramererror_code COFFObjectFile::isSymbolGlobal(DataRefImpl Symb,
178ac241fe9f0d73c6f632e4f7f89e06b698d39da54Benjamin Kramer                                          bool &Result) const {
179ac241fe9f0d73c6f632e4f7f89e06b698d39da54Benjamin Kramer  const coff_symbol *symb = toSymb(Symb);
180ac241fe9f0d73c6f632e4f7f89e06b698d39da54Benjamin Kramer  Result = (symb->StorageClass == COFF::IMAGE_SYM_CLASS_EXTERNAL);
181ac241fe9f0d73c6f632e4f7f89e06b698d39da54Benjamin Kramer  return object_error::success;
182ac241fe9f0d73c6f632e4f7f89e06b698d39da54Benjamin Kramer}
183ac241fe9f0d73c6f632e4f7f89e06b698d39da54Benjamin Kramer
18425b15777df42d5d608810f6881b6c98107481d69Michael J. Spencererror_code COFFObjectFile::getSymbolSize(DataRefImpl Symb,
18525b15777df42d5d608810f6881b6c98107481d69Michael J. Spencer                                         uint64_t &Result) const {
186a1ef8ef66075e28e020e5d2f408e0a9bae9eb9d3Michael J. Spencer  // FIXME: Return the correct size. This requires looking at all the symbols
187a1ef8ef66075e28e020e5d2f408e0a9bae9eb9d3Michael J. Spencer  //        in the same section as this symbol, and looking for either the next
188a1ef8ef66075e28e020e5d2f408e0a9bae9eb9d3Michael J. Spencer  //        symbol, or the end of the section.
18925b15777df42d5d608810f6881b6c98107481d69Michael J. Spencer  const coff_symbol *symb = toSymb(Symb);
19064388ceee00d5e8fc8750ce7967c07a83af3a5a8Michael J. Spencer  const coff_section *Section = NULL;
19125b15777df42d5d608810f6881b6c98107481d69Michael J. Spencer  if (error_code ec = getSection(symb->SectionNumber, Section))
19225b15777df42d5d608810f6881b6c98107481d69Michael J. Spencer    return ec;
19325b15777df42d5d608810f6881b6c98107481d69Michael J. Spencer  char Type;
19425b15777df42d5d608810f6881b6c98107481d69Michael J. Spencer  if (error_code ec = getSymbolNMTypeChar(Symb, Type))
19525b15777df42d5d608810f6881b6c98107481d69Michael J. Spencer    return ec;
196a1ef8ef66075e28e020e5d2f408e0a9bae9eb9d3Michael J. Spencer  if (Type == 'U' || Type == 'w')
19725b15777df42d5d608810f6881b6c98107481d69Michael J. Spencer    Result = UnknownAddressOrSize;
19825b15777df42d5d608810f6881b6c98107481d69Michael J. Spencer  else if (Section)
19925b15777df42d5d608810f6881b6c98107481d69Michael J. Spencer    Result = Section->SizeOfRawData - symb->Value;
20025b15777df42d5d608810f6881b6c98107481d69Michael J. Spencer  else
20125b15777df42d5d608810f6881b6c98107481d69Michael J. Spencer    Result = 0;
20225b15777df42d5d608810f6881b6c98107481d69Michael J. Spencer  return object_error::success;
203a1ef8ef66075e28e020e5d2f408e0a9bae9eb9d3Michael J. Spencer}
204a1ef8ef66075e28e020e5d2f408e0a9bae9eb9d3Michael J. Spencer
20525b15777df42d5d608810f6881b6c98107481d69Michael J. Spencererror_code COFFObjectFile::getSymbolNMTypeChar(DataRefImpl Symb,
20625b15777df42d5d608810f6881b6c98107481d69Michael J. Spencer                                               char &Result) const {
20725b15777df42d5d608810f6881b6c98107481d69Michael J. Spencer  const coff_symbol *symb = toSymb(Symb);
20825b15777df42d5d608810f6881b6c98107481d69Michael J. Spencer  StringRef name;
20925b15777df42d5d608810f6881b6c98107481d69Michael J. Spencer  if (error_code ec = getSymbolName(Symb, name))
21025b15777df42d5d608810f6881b6c98107481d69Michael J. Spencer    return ec;
21125b15777df42d5d608810f6881b6c98107481d69Michael J. Spencer  char ret = StringSwitch<char>(name)
212a1ef8ef66075e28e020e5d2f408e0a9bae9eb9d3Michael J. Spencer    .StartsWith(".debug", 'N')
213a1ef8ef66075e28e020e5d2f408e0a9bae9eb9d3Michael J. Spencer    .StartsWith(".sxdata", 'N')
214a1ef8ef66075e28e020e5d2f408e0a9bae9eb9d3Michael J. Spencer    .Default('?');
215a1ef8ef66075e28e020e5d2f408e0a9bae9eb9d3Michael J. Spencer
21625b15777df42d5d608810f6881b6c98107481d69Michael J. Spencer  if (ret != '?') {
21725b15777df42d5d608810f6881b6c98107481d69Michael J. Spencer    Result = ret;
21825b15777df42d5d608810f6881b6c98107481d69Michael J. Spencer    return object_error::success;
21925b15777df42d5d608810f6881b6c98107481d69Michael J. Spencer  }
220a1ef8ef66075e28e020e5d2f408e0a9bae9eb9d3Michael J. Spencer
221a1ef8ef66075e28e020e5d2f408e0a9bae9eb9d3Michael J. Spencer  uint32_t Characteristics = 0;
22225b15777df42d5d608810f6881b6c98107481d69Michael J. Spencer  if (symb->SectionNumber > 0) {
22364388ceee00d5e8fc8750ce7967c07a83af3a5a8Michael J. Spencer    const coff_section *Section = NULL;
22425b15777df42d5d608810f6881b6c98107481d69Michael J. Spencer    if (error_code ec = getSection(symb->SectionNumber, Section))
22525b15777df42d5d608810f6881b6c98107481d69Michael J. Spencer      return ec;
226a1ef8ef66075e28e020e5d2f408e0a9bae9eb9d3Michael J. Spencer    Characteristics = Section->Characteristics;
227a1ef8ef66075e28e020e5d2f408e0a9bae9eb9d3Michael J. Spencer  }
228a1ef8ef66075e28e020e5d2f408e0a9bae9eb9d3Michael J. Spencer
229a1ef8ef66075e28e020e5d2f408e0a9bae9eb9d3Michael J. Spencer  switch (symb->SectionNumber) {
230a1ef8ef66075e28e020e5d2f408e0a9bae9eb9d3Michael J. Spencer  case COFF::IMAGE_SYM_UNDEFINED:
231a1ef8ef66075e28e020e5d2f408e0a9bae9eb9d3Michael J. Spencer    // Check storage classes.
23225b15777df42d5d608810f6881b6c98107481d69Michael J. Spencer    if (symb->StorageClass == COFF::IMAGE_SYM_CLASS_WEAK_EXTERNAL) {
23325b15777df42d5d608810f6881b6c98107481d69Michael J. Spencer      Result = 'w';
23425b15777df42d5d608810f6881b6c98107481d69Michael J. Spencer      return object_error::success; // Don't do ::toupper.
23525b15777df42d5d608810f6881b6c98107481d69Michael J. Spencer    } else
236a1ef8ef66075e28e020e5d2f408e0a9bae9eb9d3Michael J. Spencer      ret = 'u';
237a1ef8ef66075e28e020e5d2f408e0a9bae9eb9d3Michael J. Spencer    break;
238a1ef8ef66075e28e020e5d2f408e0a9bae9eb9d3Michael J. Spencer  case COFF::IMAGE_SYM_ABSOLUTE:
239a1ef8ef66075e28e020e5d2f408e0a9bae9eb9d3Michael J. Spencer    ret = 'a';
240a1ef8ef66075e28e020e5d2f408e0a9bae9eb9d3Michael J. Spencer    break;
241a1ef8ef66075e28e020e5d2f408e0a9bae9eb9d3Michael J. Spencer  case COFF::IMAGE_SYM_DEBUG:
242a1ef8ef66075e28e020e5d2f408e0a9bae9eb9d3Michael J. Spencer    ret = 'n';
243a1ef8ef66075e28e020e5d2f408e0a9bae9eb9d3Michael J. Spencer    break;
244a1ef8ef66075e28e020e5d2f408e0a9bae9eb9d3Michael J. Spencer  default:
245a1ef8ef66075e28e020e5d2f408e0a9bae9eb9d3Michael J. Spencer    // Check section type.
246a1ef8ef66075e28e020e5d2f408e0a9bae9eb9d3Michael J. Spencer    if (Characteristics & COFF::IMAGE_SCN_CNT_CODE)
247a1ef8ef66075e28e020e5d2f408e0a9bae9eb9d3Michael J. Spencer      ret = 't';
248a1ef8ef66075e28e020e5d2f408e0a9bae9eb9d3Michael J. Spencer    else if (  Characteristics & COFF::IMAGE_SCN_MEM_READ
249a1ef8ef66075e28e020e5d2f408e0a9bae9eb9d3Michael J. Spencer            && ~Characteristics & COFF::IMAGE_SCN_MEM_WRITE) // Read only.
250a1ef8ef66075e28e020e5d2f408e0a9bae9eb9d3Michael J. Spencer      ret = 'r';
251a1ef8ef66075e28e020e5d2f408e0a9bae9eb9d3Michael J. Spencer    else if (Characteristics & COFF::IMAGE_SCN_CNT_INITIALIZED_DATA)
252a1ef8ef66075e28e020e5d2f408e0a9bae9eb9d3Michael J. Spencer      ret = 'd';
253a1ef8ef66075e28e020e5d2f408e0a9bae9eb9d3Michael J. Spencer    else if (Characteristics & COFF::IMAGE_SCN_CNT_UNINITIALIZED_DATA)
254a1ef8ef66075e28e020e5d2f408e0a9bae9eb9d3Michael J. Spencer      ret = 'b';
255a1ef8ef66075e28e020e5d2f408e0a9bae9eb9d3Michael J. Spencer    else if (Characteristics & COFF::IMAGE_SCN_LNK_INFO)
256a1ef8ef66075e28e020e5d2f408e0a9bae9eb9d3Michael J. Spencer      ret = 'i';
257a1ef8ef66075e28e020e5d2f408e0a9bae9eb9d3Michael J. Spencer
258a1ef8ef66075e28e020e5d2f408e0a9bae9eb9d3Michael J. Spencer    // Check for section symbol.
259a1ef8ef66075e28e020e5d2f408e0a9bae9eb9d3Michael J. Spencer    else if (  symb->StorageClass == COFF::IMAGE_SYM_CLASS_STATIC
260a1ef8ef66075e28e020e5d2f408e0a9bae9eb9d3Michael J. Spencer            && symb->Value == 0)
261a1ef8ef66075e28e020e5d2f408e0a9bae9eb9d3Michael J. Spencer       ret = 's';
262a1ef8ef66075e28e020e5d2f408e0a9bae9eb9d3Michael J. Spencer  }
263a1ef8ef66075e28e020e5d2f408e0a9bae9eb9d3Michael J. Spencer
264a1ef8ef66075e28e020e5d2f408e0a9bae9eb9d3Michael J. Spencer  if (symb->StorageClass == COFF::IMAGE_SYM_CLASS_EXTERNAL)
265a1ef8ef66075e28e020e5d2f408e0a9bae9eb9d3Michael J. Spencer    ret = ::toupper(ret);
266a1ef8ef66075e28e020e5d2f408e0a9bae9eb9d3Michael J. Spencer
26725b15777df42d5d608810f6881b6c98107481d69Michael J. Spencer  Result = ret;
26825b15777df42d5d608810f6881b6c98107481d69Michael J. Spencer  return object_error::success;
269a1ef8ef66075e28e020e5d2f408e0a9bae9eb9d3Michael J. Spencer}
270a1ef8ef66075e28e020e5d2f408e0a9bae9eb9d3Michael J. Spencer
27125b15777df42d5d608810f6881b6c98107481d69Michael J. Spencererror_code COFFObjectFile::isSymbolInternal(DataRefImpl Symb,
27225b15777df42d5d608810f6881b6c98107481d69Michael J. Spencer                                            bool &Result) const {
27325b15777df42d5d608810f6881b6c98107481d69Michael J. Spencer  Result = false;
27425b15777df42d5d608810f6881b6c98107481d69Michael J. Spencer  return object_error::success;
275a1ef8ef66075e28e020e5d2f408e0a9bae9eb9d3Michael J. Spencer}
276a1ef8ef66075e28e020e5d2f408e0a9bae9eb9d3Michael J. Spencer
27725b15777df42d5d608810f6881b6c98107481d69Michael J. Spencererror_code COFFObjectFile::getSectionNext(DataRefImpl Sec,
27825b15777df42d5d608810f6881b6c98107481d69Michael J. Spencer                                          SectionRef &Result) const {
27925b15777df42d5d608810f6881b6c98107481d69Michael J. Spencer  const coff_section *sec = toSec(Sec);
280a1ef8ef66075e28e020e5d2f408e0a9bae9eb9d3Michael J. Spencer  sec += 1;
28125b15777df42d5d608810f6881b6c98107481d69Michael J. Spencer  Sec.p = reinterpret_cast<uintptr_t>(sec);
28225b15777df42d5d608810f6881b6c98107481d69Michael J. Spencer  Result = SectionRef(Sec, this);
28325b15777df42d5d608810f6881b6c98107481d69Michael J. Spencer  return object_error::success;
284a1ef8ef66075e28e020e5d2f408e0a9bae9eb9d3Michael J. Spencer}
285a1ef8ef66075e28e020e5d2f408e0a9bae9eb9d3Michael J. Spencer
28625b15777df42d5d608810f6881b6c98107481d69Michael J. Spencererror_code COFFObjectFile::getSectionName(DataRefImpl Sec,
28725b15777df42d5d608810f6881b6c98107481d69Michael J. Spencer                                          StringRef &Result) const {
28825b15777df42d5d608810f6881b6c98107481d69Michael J. Spencer  const coff_section *sec = toSec(Sec);
289a1ef8ef66075e28e020e5d2f408e0a9bae9eb9d3Michael J. Spencer  StringRef name;
290a1ef8ef66075e28e020e5d2f408e0a9bae9eb9d3Michael J. Spencer  if (sec->Name[7] == 0)
291a1ef8ef66075e28e020e5d2f408e0a9bae9eb9d3Michael J. Spencer    // Null terminated, let ::strlen figure out the length.
292a1ef8ef66075e28e020e5d2f408e0a9bae9eb9d3Michael J. Spencer    name = sec->Name;
293a1ef8ef66075e28e020e5d2f408e0a9bae9eb9d3Michael J. Spencer  else
294a1ef8ef66075e28e020e5d2f408e0a9bae9eb9d3Michael J. Spencer    // Not null terminated, use all 8 bytes.
295a1ef8ef66075e28e020e5d2f408e0a9bae9eb9d3Michael J. Spencer    name = StringRef(sec->Name, 8);
296a1ef8ef66075e28e020e5d2f408e0a9bae9eb9d3Michael J. Spencer
297a1ef8ef66075e28e020e5d2f408e0a9bae9eb9d3Michael J. Spencer  // Check for string table entry. First byte is '/'.
298a1ef8ef66075e28e020e5d2f408e0a9bae9eb9d3Michael J. Spencer  if (name[0] == '/') {
299a1ef8ef66075e28e020e5d2f408e0a9bae9eb9d3Michael J. Spencer    uint32_t Offset;
300539d8d8a72995d08afe7b986fe98a1dc7fec4b0aEric Christopher    name.substr(1).getAsInteger(10, Offset);
30125b15777df42d5d608810f6881b6c98107481d69Michael J. Spencer    if (error_code ec = getString(Offset, name))
30225b15777df42d5d608810f6881b6c98107481d69Michael J. Spencer      return ec;
303a1ef8ef66075e28e020e5d2f408e0a9bae9eb9d3Michael J. Spencer  }
304a1ef8ef66075e28e020e5d2f408e0a9bae9eb9d3Michael J. Spencer
30525b15777df42d5d608810f6881b6c98107481d69Michael J. Spencer  Result = name;
30625b15777df42d5d608810f6881b6c98107481d69Michael J. Spencer  return object_error::success;
307a1ef8ef66075e28e020e5d2f408e0a9bae9eb9d3Michael J. Spencer}
308a1ef8ef66075e28e020e5d2f408e0a9bae9eb9d3Michael J. Spencer
30925b15777df42d5d608810f6881b6c98107481d69Michael J. Spencererror_code COFFObjectFile::getSectionAddress(DataRefImpl Sec,
31025b15777df42d5d608810f6881b6c98107481d69Michael J. Spencer                                             uint64_t &Result) const {
31125b15777df42d5d608810f6881b6c98107481d69Michael J. Spencer  const coff_section *sec = toSec(Sec);
31225b15777df42d5d608810f6881b6c98107481d69Michael J. Spencer  Result = sec->VirtualAddress;
31325b15777df42d5d608810f6881b6c98107481d69Michael J. Spencer  return object_error::success;
314a1ef8ef66075e28e020e5d2f408e0a9bae9eb9d3Michael J. Spencer}
315a1ef8ef66075e28e020e5d2f408e0a9bae9eb9d3Michael J. Spencer
31625b15777df42d5d608810f6881b6c98107481d69Michael J. Spencererror_code COFFObjectFile::getSectionSize(DataRefImpl Sec,
31725b15777df42d5d608810f6881b6c98107481d69Michael J. Spencer                                          uint64_t &Result) const {
31825b15777df42d5d608810f6881b6c98107481d69Michael J. Spencer  const coff_section *sec = toSec(Sec);
31925b15777df42d5d608810f6881b6c98107481d69Michael J. Spencer  Result = sec->SizeOfRawData;
32025b15777df42d5d608810f6881b6c98107481d69Michael J. Spencer  return object_error::success;
321a1ef8ef66075e28e020e5d2f408e0a9bae9eb9d3Michael J. Spencer}
322a1ef8ef66075e28e020e5d2f408e0a9bae9eb9d3Michael J. Spencer
32325b15777df42d5d608810f6881b6c98107481d69Michael J. Spencererror_code COFFObjectFile::getSectionContents(DataRefImpl Sec,
32425b15777df42d5d608810f6881b6c98107481d69Michael J. Spencer                                              StringRef &Result) const {
32525b15777df42d5d608810f6881b6c98107481d69Michael J. Spencer  const coff_section *sec = toSec(Sec);
32625b15777df42d5d608810f6881b6c98107481d69Michael J. Spencer  // The only thing that we need to verify is that the contents is contained
32725b15777df42d5d608810f6881b6c98107481d69Michael J. Spencer  // within the file bounds. We don't need to make sure it doesn't cover other
32825b15777df42d5d608810f6881b6c98107481d69Michael J. Spencer  // data, as there's nothing that says that is not allowed.
32925b15777df42d5d608810f6881b6c98107481d69Michael J. Spencer  uintptr_t con_start = uintptr_t(base()) + sec->PointerToRawData;
33025b15777df42d5d608810f6881b6c98107481d69Michael J. Spencer  uintptr_t con_end = con_start + sec->SizeOfRawData;
33125b15777df42d5d608810f6881b6c98107481d69Michael J. Spencer  if (con_end >= uintptr_t(Data->getBufferEnd()))
33225b15777df42d5d608810f6881b6c98107481d69Michael J. Spencer    return object_error::parse_failed;
33325b15777df42d5d608810f6881b6c98107481d69Michael J. Spencer  Result = StringRef(reinterpret_cast<const char*>(con_start),
33425b15777df42d5d608810f6881b6c98107481d69Michael J. Spencer                     sec->SizeOfRawData);
33525b15777df42d5d608810f6881b6c98107481d69Michael J. Spencer  return object_error::success;
336a1ef8ef66075e28e020e5d2f408e0a9bae9eb9d3Michael J. Spencer}
337a1ef8ef66075e28e020e5d2f408e0a9bae9eb9d3Michael J. Spencer
33825b15777df42d5d608810f6881b6c98107481d69Michael J. Spencererror_code COFFObjectFile::isSectionText(DataRefImpl Sec,
33925b15777df42d5d608810f6881b6c98107481d69Michael J. Spencer                                         bool &Result) const {
34025b15777df42d5d608810f6881b6c98107481d69Michael J. Spencer  const coff_section *sec = toSec(Sec);
34125b15777df42d5d608810f6881b6c98107481d69Michael J. Spencer  Result = sec->Characteristics & COFF::IMAGE_SCN_CNT_CODE;
34213afc5eff2d7370ab486d5039886ab8bbf9039daMichael J. Spencer  return object_error::success;
34313afc5eff2d7370ab486d5039886ab8bbf9039daMichael J. Spencer}
34413afc5eff2d7370ab486d5039886ab8bbf9039daMichael J. Spencer
34513afc5eff2d7370ab486d5039886ab8bbf9039daMichael J. Spencererror_code COFFObjectFile::isSectionData(DataRefImpl Sec,
34613afc5eff2d7370ab486d5039886ab8bbf9039daMichael J. Spencer                                         bool &Result) const {
34713afc5eff2d7370ab486d5039886ab8bbf9039daMichael J. Spencer  const coff_section *sec = toSec(Sec);
34813afc5eff2d7370ab486d5039886ab8bbf9039daMichael J. Spencer  Result = sec->Characteristics & COFF::IMAGE_SCN_CNT_INITIALIZED_DATA;
34913afc5eff2d7370ab486d5039886ab8bbf9039daMichael J. Spencer  return object_error::success;
35013afc5eff2d7370ab486d5039886ab8bbf9039daMichael J. Spencer}
35113afc5eff2d7370ab486d5039886ab8bbf9039daMichael J. Spencer
35213afc5eff2d7370ab486d5039886ab8bbf9039daMichael J. Spencererror_code COFFObjectFile::isSectionBSS(DataRefImpl Sec,
35313afc5eff2d7370ab486d5039886ab8bbf9039daMichael J. Spencer                                        bool &Result) const {
35413afc5eff2d7370ab486d5039886ab8bbf9039daMichael J. Spencer  const coff_section *sec = toSec(Sec);
35513afc5eff2d7370ab486d5039886ab8bbf9039daMichael J. Spencer  Result = sec->Characteristics & COFF::IMAGE_SCN_CNT_UNINITIALIZED_DATA;
35625b15777df42d5d608810f6881b6c98107481d69Michael J. Spencer  return object_error::success;
357a1ef8ef66075e28e020e5d2f408e0a9bae9eb9d3Michael J. Spencer}
358a1ef8ef66075e28e020e5d2f408e0a9bae9eb9d3Michael J. Spencer
35907ea23aa2d17f701fa125442c20c1eba75b55fdbBenjamin Kramererror_code COFFObjectFile::sectionContainsSymbol(DataRefImpl Sec,
36007ea23aa2d17f701fa125442c20c1eba75b55fdbBenjamin Kramer                                                 DataRefImpl Symb,
36107ea23aa2d17f701fa125442c20c1eba75b55fdbBenjamin Kramer                                                 bool &Result) const {
36207ea23aa2d17f701fa125442c20c1eba75b55fdbBenjamin Kramer  // FIXME: Unimplemented.
36307ea23aa2d17f701fa125442c20c1eba75b55fdbBenjamin Kramer  Result = false;
36407ea23aa2d17f701fa125442c20c1eba75b55fdbBenjamin Kramer  return object_error::success;
36507ea23aa2d17f701fa125442c20c1eba75b55fdbBenjamin Kramer}
36607ea23aa2d17f701fa125442c20c1eba75b55fdbBenjamin Kramer
367001c9205fca2220480589ec355cb6ec701a37e08Michael J. SpencerCOFFObjectFile::COFFObjectFile(MemoryBuffer *Object, error_code &ec)
368001c9205fca2220480589ec355cb6ec701a37e08Michael J. Spencer  : ObjectFile(Binary::isCOFF, Object, ec) {
36925b15777df42d5d608810f6881b6c98107481d69Michael J. Spencer  // Check that we at least have enough room for a header.
37025b15777df42d5d608810f6881b6c98107481d69Michael J. Spencer  if (!checkSize(Data, ec, sizeof(coff_file_header))) return;
371539d8d8a72995d08afe7b986fe98a1dc7fec4b0aEric Christopher
37225b15777df42d5d608810f6881b6c98107481d69Michael J. Spencer  // The actual starting location of the COFF header in the file. This can be
37325b15777df42d5d608810f6881b6c98107481d69Michael J. Spencer  // non-zero in PE/COFF files.
37425b15777df42d5d608810f6881b6c98107481d69Michael J. Spencer  uint64_t HeaderStart = 0;
375539d8d8a72995d08afe7b986fe98a1dc7fec4b0aEric Christopher
37625b15777df42d5d608810f6881b6c98107481d69Michael J. Spencer  // Check if this is a PE/COFF file.
377001c9205fca2220480589ec355cb6ec701a37e08Michael J. Spencer  if (base()[0] == 0x4d && base()[1] == 0x5a) {
378539d8d8a72995d08afe7b986fe98a1dc7fec4b0aEric Christopher    // PE/COFF, seek through MS-DOS compatibility stub and 4-byte
379539d8d8a72995d08afe7b986fe98a1dc7fec4b0aEric Christopher    // PE signature to find 'normal' COFF header.
38025b15777df42d5d608810f6881b6c98107481d69Michael J. Spencer    if (!checkSize(Data, ec, 0x3c + 8)) return;
38125b15777df42d5d608810f6881b6c98107481d69Michael J. Spencer    HeaderStart += *reinterpret_cast<const ulittle32_t *>(base() + 0x3c);
38225b15777df42d5d608810f6881b6c98107481d69Michael J. Spencer    // Check the PE header. ("PE\0\0")
3833209a03dafe1a23fe74c933cebd9f9c92a2a3616Benjamin Kramer    if (std::memcmp(base() + HeaderStart, "PE\0\0", 4) != 0) {
38425b15777df42d5d608810f6881b6c98107481d69Michael J. Spencer      ec = object_error::parse_failed;
38525b15777df42d5d608810f6881b6c98107481d69Michael J. Spencer      return;
38625b15777df42d5d608810f6881b6c98107481d69Michael J. Spencer    }
38725b15777df42d5d608810f6881b6c98107481d69Michael J. Spencer    HeaderStart += 4; // Skip the PE Header.
388539d8d8a72995d08afe7b986fe98a1dc7fec4b0aEric Christopher  }
389539d8d8a72995d08afe7b986fe98a1dc7fec4b0aEric Christopher
39025b15777df42d5d608810f6881b6c98107481d69Michael J. Spencer  Header = reinterpret_cast<const coff_file_header *>(base() + HeaderStart);
39125b15777df42d5d608810f6881b6c98107481d69Michael J. Spencer  if (!checkAddr(Data, ec, uintptr_t(Header), sizeof(coff_file_header)))
39225b15777df42d5d608810f6881b6c98107481d69Michael J. Spencer    return;
3930fcab076f0358890e2f1b213f4303c780e05d99dBenjamin Kramer
394a1ef8ef66075e28e020e5d2f408e0a9bae9eb9d3Michael J. Spencer  SectionTable =
395001c9205fca2220480589ec355cb6ec701a37e08Michael J. Spencer    reinterpret_cast<const coff_section *>( base()
39625b15777df42d5d608810f6881b6c98107481d69Michael J. Spencer                                          + HeaderStart
397a1ef8ef66075e28e020e5d2f408e0a9bae9eb9d3Michael J. Spencer                                          + sizeof(coff_file_header)
398a1ef8ef66075e28e020e5d2f408e0a9bae9eb9d3Michael J. Spencer                                          + Header->SizeOfOptionalHeader);
39925b15777df42d5d608810f6881b6c98107481d69Michael J. Spencer  if (!checkAddr(Data, ec, uintptr_t(SectionTable),
40025b15777df42d5d608810f6881b6c98107481d69Michael J. Spencer                 Header->NumberOfSections * sizeof(coff_section)))
40125b15777df42d5d608810f6881b6c98107481d69Michael J. Spencer    return;
40225b15777df42d5d608810f6881b6c98107481d69Michael J. Spencer
403a1ef8ef66075e28e020e5d2f408e0a9bae9eb9d3Michael J. Spencer  SymbolTable =
404001c9205fca2220480589ec355cb6ec701a37e08Michael J. Spencer    reinterpret_cast<const coff_symbol *>(base()
40525b15777df42d5d608810f6881b6c98107481d69Michael J. Spencer                                          + Header->PointerToSymbolTable);
40625b15777df42d5d608810f6881b6c98107481d69Michael J. Spencer  if (!checkAddr(Data, ec, uintptr_t(SymbolTable),
40725b15777df42d5d608810f6881b6c98107481d69Michael J. Spencer                 Header->NumberOfSymbols * sizeof(coff_symbol)))
40825b15777df42d5d608810f6881b6c98107481d69Michael J. Spencer    return;
409a1ef8ef66075e28e020e5d2f408e0a9bae9eb9d3Michael J. Spencer
410a1ef8ef66075e28e020e5d2f408e0a9bae9eb9d3Michael J. Spencer  // Find string table.
411001c9205fca2220480589ec355cb6ec701a37e08Michael J. Spencer  StringTable = reinterpret_cast<const char *>(base())
41225b15777df42d5d608810f6881b6c98107481d69Michael J. Spencer                + Header->PointerToSymbolTable
41325b15777df42d5d608810f6881b6c98107481d69Michael J. Spencer                + Header->NumberOfSymbols * sizeof(coff_symbol);
41425b15777df42d5d608810f6881b6c98107481d69Michael J. Spencer  if (!checkAddr(Data, ec, uintptr_t(StringTable), sizeof(ulittle32_t)))
41525b15777df42d5d608810f6881b6c98107481d69Michael J. Spencer    return;
41625b15777df42d5d608810f6881b6c98107481d69Michael J. Spencer
41725b15777df42d5d608810f6881b6c98107481d69Michael J. Spencer  StringTableSize = *reinterpret_cast<const ulittle32_t *>(StringTable);
41825b15777df42d5d608810f6881b6c98107481d69Michael J. Spencer  if (!checkAddr(Data, ec, uintptr_t(StringTable), StringTableSize))
41925b15777df42d5d608810f6881b6c98107481d69Michael J. Spencer    return;
42025b15777df42d5d608810f6881b6c98107481d69Michael J. Spencer  // Check that the string table is null terminated if has any in it.
42125b15777df42d5d608810f6881b6c98107481d69Michael J. Spencer  if (StringTableSize < 4
42225b15777df42d5d608810f6881b6c98107481d69Michael J. Spencer      || (StringTableSize > 4 && StringTable[StringTableSize - 1] != 0)) {
42325b15777df42d5d608810f6881b6c98107481d69Michael J. Spencer    ec = object_error::parse_failed;
42425b15777df42d5d608810f6881b6c98107481d69Michael J. Spencer    return;
42525b15777df42d5d608810f6881b6c98107481d69Michael J. Spencer  }
4260fcab076f0358890e2f1b213f4303c780e05d99dBenjamin Kramer
42725b15777df42d5d608810f6881b6c98107481d69Michael J. Spencer  ec = object_error::success;
428a1ef8ef66075e28e020e5d2f408e0a9bae9eb9d3Michael J. Spencer}
429a1ef8ef66075e28e020e5d2f408e0a9bae9eb9d3Michael J. Spencer
430a1ef8ef66075e28e020e5d2f408e0a9bae9eb9d3Michael J. SpencerObjectFile::symbol_iterator COFFObjectFile::begin_symbols() const {
4317acdb4d237181976b04e72f6a6c329c3b2604440Michael J. Spencer  DataRefImpl ret;
43225b15777df42d5d608810f6881b6c98107481d69Michael J. Spencer  std::memset(&ret, 0, sizeof(DataRefImpl));
4337acdb4d237181976b04e72f6a6c329c3b2604440Michael J. Spencer  ret.p = reinterpret_cast<intptr_t>(SymbolTable);
4347acdb4d237181976b04e72f6a6c329c3b2604440Michael J. Spencer  return symbol_iterator(SymbolRef(ret, this));
435a1ef8ef66075e28e020e5d2f408e0a9bae9eb9d3Michael J. Spencer}
436a1ef8ef66075e28e020e5d2f408e0a9bae9eb9d3Michael J. Spencer
437a1ef8ef66075e28e020e5d2f408e0a9bae9eb9d3Michael J. SpencerObjectFile::symbol_iterator COFFObjectFile::end_symbols() const {
438a1ef8ef66075e28e020e5d2f408e0a9bae9eb9d3Michael J. Spencer  // The symbol table ends where the string table begins.
4397acdb4d237181976b04e72f6a6c329c3b2604440Michael J. Spencer  DataRefImpl ret;
44025b15777df42d5d608810f6881b6c98107481d69Michael J. Spencer  std::memset(&ret, 0, sizeof(DataRefImpl));
4417acdb4d237181976b04e72f6a6c329c3b2604440Michael J. Spencer  ret.p = reinterpret_cast<intptr_t>(StringTable);
4427acdb4d237181976b04e72f6a6c329c3b2604440Michael J. Spencer  return symbol_iterator(SymbolRef(ret, this));
443a1ef8ef66075e28e020e5d2f408e0a9bae9eb9d3Michael J. Spencer}
444a1ef8ef66075e28e020e5d2f408e0a9bae9eb9d3Michael J. Spencer
445a1ef8ef66075e28e020e5d2f408e0a9bae9eb9d3Michael J. SpencerObjectFile::section_iterator COFFObjectFile::begin_sections() const {
4467acdb4d237181976b04e72f6a6c329c3b2604440Michael J. Spencer  DataRefImpl ret;
44725b15777df42d5d608810f6881b6c98107481d69Michael J. Spencer  std::memset(&ret, 0, sizeof(DataRefImpl));
4487acdb4d237181976b04e72f6a6c329c3b2604440Michael J. Spencer  ret.p = reinterpret_cast<intptr_t>(SectionTable);
4497acdb4d237181976b04e72f6a6c329c3b2604440Michael J. Spencer  return section_iterator(SectionRef(ret, this));
450a1ef8ef66075e28e020e5d2f408e0a9bae9eb9d3Michael J. Spencer}
451a1ef8ef66075e28e020e5d2f408e0a9bae9eb9d3Michael J. Spencer
452a1ef8ef66075e28e020e5d2f408e0a9bae9eb9d3Michael J. SpencerObjectFile::section_iterator COFFObjectFile::end_sections() const {
4537acdb4d237181976b04e72f6a6c329c3b2604440Michael J. Spencer  DataRefImpl ret;
45425b15777df42d5d608810f6881b6c98107481d69Michael J. Spencer  std::memset(&ret, 0, sizeof(DataRefImpl));
4557acdb4d237181976b04e72f6a6c329c3b2604440Michael J. Spencer  ret.p = reinterpret_cast<intptr_t>(SectionTable + Header->NumberOfSections);
4567acdb4d237181976b04e72f6a6c329c3b2604440Michael J. Spencer  return section_iterator(SectionRef(ret, this));
457a1ef8ef66075e28e020e5d2f408e0a9bae9eb9d3Michael J. Spencer}
458a1ef8ef66075e28e020e5d2f408e0a9bae9eb9d3Michael J. Spencer
459a1ef8ef66075e28e020e5d2f408e0a9bae9eb9d3Michael J. Spenceruint8_t COFFObjectFile::getBytesInAddress() const {
4607acdb4d237181976b04e72f6a6c329c3b2604440Michael J. Spencer  return getArch() == Triple::x86_64 ? 8 : 4;
461a1ef8ef66075e28e020e5d2f408e0a9bae9eb9d3Michael J. Spencer}
462a1ef8ef66075e28e020e5d2f408e0a9bae9eb9d3Michael J. Spencer
463a1ef8ef66075e28e020e5d2f408e0a9bae9eb9d3Michael J. SpencerStringRef COFFObjectFile::getFileFormatName() const {
464a1ef8ef66075e28e020e5d2f408e0a9bae9eb9d3Michael J. Spencer  switch(Header->Machine) {
465a1ef8ef66075e28e020e5d2f408e0a9bae9eb9d3Michael J. Spencer  case COFF::IMAGE_FILE_MACHINE_I386:
466a1ef8ef66075e28e020e5d2f408e0a9bae9eb9d3Michael J. Spencer    return "COFF-i386";
467a1ef8ef66075e28e020e5d2f408e0a9bae9eb9d3Michael J. Spencer  case COFF::IMAGE_FILE_MACHINE_AMD64:
468a1ef8ef66075e28e020e5d2f408e0a9bae9eb9d3Michael J. Spencer    return "COFF-x86-64";
469a1ef8ef66075e28e020e5d2f408e0a9bae9eb9d3Michael J. Spencer  default:
470a1ef8ef66075e28e020e5d2f408e0a9bae9eb9d3Michael J. Spencer    return "COFF-<unknown arch>";
471a1ef8ef66075e28e020e5d2f408e0a9bae9eb9d3Michael J. Spencer  }
472a1ef8ef66075e28e020e5d2f408e0a9bae9eb9d3Michael J. Spencer}
473a1ef8ef66075e28e020e5d2f408e0a9bae9eb9d3Michael J. Spencer
474a1ef8ef66075e28e020e5d2f408e0a9bae9eb9d3Michael J. Spencerunsigned COFFObjectFile::getArch() const {
475a1ef8ef66075e28e020e5d2f408e0a9bae9eb9d3Michael J. Spencer  switch(Header->Machine) {
476a1ef8ef66075e28e020e5d2f408e0a9bae9eb9d3Michael J. Spencer  case COFF::IMAGE_FILE_MACHINE_I386:
477a1ef8ef66075e28e020e5d2f408e0a9bae9eb9d3Michael J. Spencer    return Triple::x86;
478a1ef8ef66075e28e020e5d2f408e0a9bae9eb9d3Michael J. Spencer  case COFF::IMAGE_FILE_MACHINE_AMD64:
479a1ef8ef66075e28e020e5d2f408e0a9bae9eb9d3Michael J. Spencer    return Triple::x86_64;
480a1ef8ef66075e28e020e5d2f408e0a9bae9eb9d3Michael J. Spencer  default:
481a1ef8ef66075e28e020e5d2f408e0a9bae9eb9d3Michael J. Spencer    return Triple::UnknownArch;
482a1ef8ef66075e28e020e5d2f408e0a9bae9eb9d3Michael J. Spencer  }
483a1ef8ef66075e28e020e5d2f408e0a9bae9eb9d3Michael J. Spencer}
484a1ef8ef66075e28e020e5d2f408e0a9bae9eb9d3Michael J. Spencer
48525b15777df42d5d608810f6881b6c98107481d69Michael J. Spencererror_code COFFObjectFile::getSection(int32_t index,
48625b15777df42d5d608810f6881b6c98107481d69Michael J. Spencer                                      const coff_section *&Result) const {
48725b15777df42d5d608810f6881b6c98107481d69Michael J. Spencer  // Check for special index values.
48825b15777df42d5d608810f6881b6c98107481d69Michael J. Spencer  if (index == COFF::IMAGE_SYM_UNDEFINED ||
48925b15777df42d5d608810f6881b6c98107481d69Michael J. Spencer      index == COFF::IMAGE_SYM_ABSOLUTE ||
49025b15777df42d5d608810f6881b6c98107481d69Michael J. Spencer      index == COFF::IMAGE_SYM_DEBUG)
49125b15777df42d5d608810f6881b6c98107481d69Michael J. Spencer    Result = NULL;
49225b15777df42d5d608810f6881b6c98107481d69Michael J. Spencer  else if (index > 0 && index <= Header->NumberOfSections)
49325b15777df42d5d608810f6881b6c98107481d69Michael J. Spencer    // We already verified the section table data, so no need to check again.
49425b15777df42d5d608810f6881b6c98107481d69Michael J. Spencer    Result = SectionTable + (index - 1);
49525b15777df42d5d608810f6881b6c98107481d69Michael J. Spencer  else
49625b15777df42d5d608810f6881b6c98107481d69Michael J. Spencer    return object_error::parse_failed;
49725b15777df42d5d608810f6881b6c98107481d69Michael J. Spencer  return object_error::success;
498a1ef8ef66075e28e020e5d2f408e0a9bae9eb9d3Michael J. Spencer}
499a1ef8ef66075e28e020e5d2f408e0a9bae9eb9d3Michael J. Spencer
50025b15777df42d5d608810f6881b6c98107481d69Michael J. Spencererror_code COFFObjectFile::getString(uint32_t offset,
50125b15777df42d5d608810f6881b6c98107481d69Michael J. Spencer                                     StringRef &Result) const {
50225b15777df42d5d608810f6881b6c98107481d69Michael J. Spencer  if (StringTableSize <= 4)
50325b15777df42d5d608810f6881b6c98107481d69Michael J. Spencer    // Tried to get a string from an empty string table.
50425b15777df42d5d608810f6881b6c98107481d69Michael J. Spencer    return object_error::parse_failed;
50525b15777df42d5d608810f6881b6c98107481d69Michael J. Spencer  if (offset >= StringTableSize)
50625b15777df42d5d608810f6881b6c98107481d69Michael J. Spencer    return object_error::unexpected_eof;
50725b15777df42d5d608810f6881b6c98107481d69Michael J. Spencer  Result = StringRef(StringTable + offset);
50825b15777df42d5d608810f6881b6c98107481d69Michael J. Spencer  return object_error::success;
509a1ef8ef66075e28e020e5d2f408e0a9bae9eb9d3Michael J. Spencer}
510a1ef8ef66075e28e020e5d2f408e0a9bae9eb9d3Michael J. Spencer
5110fcab076f0358890e2f1b213f4303c780e05d99dBenjamin Kramerconst coff_relocation *COFFObjectFile::toRel(DataRefImpl Rel) const {
5120fcab076f0358890e2f1b213f4303c780e05d99dBenjamin Kramer  assert(Rel.d.b < Header->NumberOfSections && "Section index out of range!");
513cee58a69fa3f0f291c0c88ce0d29099a95495ae7Benjamin Kramer  const coff_section *Sect = NULL;
5140fcab076f0358890e2f1b213f4303c780e05d99dBenjamin Kramer  getSection(Rel.d.b, Sect);
5150fcab076f0358890e2f1b213f4303c780e05d99dBenjamin Kramer  assert(Rel.d.a < Sect->NumberOfRelocations && "Relocation index out of range!");
5160fcab076f0358890e2f1b213f4303c780e05d99dBenjamin Kramer  return
5170fcab076f0358890e2f1b213f4303c780e05d99dBenjamin Kramer    reinterpret_cast<const coff_relocation*>(base() +
5180fcab076f0358890e2f1b213f4303c780e05d99dBenjamin Kramer                                             Sect->PointerToRelocations) +
5190fcab076f0358890e2f1b213f4303c780e05d99dBenjamin Kramer                                             Rel.d.a;
5200fcab076f0358890e2f1b213f4303c780e05d99dBenjamin Kramer}
5210fcab076f0358890e2f1b213f4303c780e05d99dBenjamin Kramererror_code COFFObjectFile::getRelocationNext(DataRefImpl Rel,
5220fcab076f0358890e2f1b213f4303c780e05d99dBenjamin Kramer                                             RelocationRef &Res) const {
5230fcab076f0358890e2f1b213f4303c780e05d99dBenjamin Kramer  const coff_section *Sect = NULL;
5240fcab076f0358890e2f1b213f4303c780e05d99dBenjamin Kramer  if (error_code ec = getSection(Rel.d.b, Sect))
5250fcab076f0358890e2f1b213f4303c780e05d99dBenjamin Kramer    return ec;
5260fcab076f0358890e2f1b213f4303c780e05d99dBenjamin Kramer  if (++Rel.d.a >= Sect->NumberOfRelocations) {
5270fcab076f0358890e2f1b213f4303c780e05d99dBenjamin Kramer    Rel.d.a = 0;
5280fcab076f0358890e2f1b213f4303c780e05d99dBenjamin Kramer    while (++Rel.d.b < Header->NumberOfSections) {
529cee58a69fa3f0f291c0c88ce0d29099a95495ae7Benjamin Kramer      const coff_section *Sect = NULL;
5300fcab076f0358890e2f1b213f4303c780e05d99dBenjamin Kramer      getSection(Rel.d.b, Sect);
5310fcab076f0358890e2f1b213f4303c780e05d99dBenjamin Kramer      if (Sect->NumberOfRelocations > 0)
5320fcab076f0358890e2f1b213f4303c780e05d99dBenjamin Kramer        break;
5330fcab076f0358890e2f1b213f4303c780e05d99dBenjamin Kramer    }
5340fcab076f0358890e2f1b213f4303c780e05d99dBenjamin Kramer  }
5350fcab076f0358890e2f1b213f4303c780e05d99dBenjamin Kramer  Res = RelocationRef(Rel, this);
5360fcab076f0358890e2f1b213f4303c780e05d99dBenjamin Kramer  return object_error::success;
5370fcab076f0358890e2f1b213f4303c780e05d99dBenjamin Kramer}
5380fcab076f0358890e2f1b213f4303c780e05d99dBenjamin Kramererror_code COFFObjectFile::getRelocationAddress(DataRefImpl Rel,
5390fcab076f0358890e2f1b213f4303c780e05d99dBenjamin Kramer                                                uint64_t &Res) const {
540cee58a69fa3f0f291c0c88ce0d29099a95495ae7Benjamin Kramer  const coff_section *Sect = NULL;
5410fcab076f0358890e2f1b213f4303c780e05d99dBenjamin Kramer  if (error_code ec = getSection(Rel.d.b, Sect))
5420fcab076f0358890e2f1b213f4303c780e05d99dBenjamin Kramer    return ec;
5430fcab076f0358890e2f1b213f4303c780e05d99dBenjamin Kramer  const coff_relocation* R = toRel(Rel);
5440fcab076f0358890e2f1b213f4303c780e05d99dBenjamin Kramer  Res = reinterpret_cast<uintptr_t>(base() +
5450fcab076f0358890e2f1b213f4303c780e05d99dBenjamin Kramer                                    Sect->PointerToRawData +
5460fcab076f0358890e2f1b213f4303c780e05d99dBenjamin Kramer                                    R->VirtualAddress);
5470fcab076f0358890e2f1b213f4303c780e05d99dBenjamin Kramer  return object_error::success;
5480fcab076f0358890e2f1b213f4303c780e05d99dBenjamin Kramer}
5490fcab076f0358890e2f1b213f4303c780e05d99dBenjamin Kramererror_code COFFObjectFile::getRelocationSymbol(DataRefImpl Rel,
5500fcab076f0358890e2f1b213f4303c780e05d99dBenjamin Kramer                                               SymbolRef &Res) const {
5510fcab076f0358890e2f1b213f4303c780e05d99dBenjamin Kramer  const coff_relocation* R = toRel(Rel);
5520fcab076f0358890e2f1b213f4303c780e05d99dBenjamin Kramer  DataRefImpl Symb;
5530fcab076f0358890e2f1b213f4303c780e05d99dBenjamin Kramer  Symb.p = reinterpret_cast<uintptr_t>(SymbolTable + R->SymbolTableIndex);
5540fcab076f0358890e2f1b213f4303c780e05d99dBenjamin Kramer  Res = SymbolRef(Symb, this);
5550fcab076f0358890e2f1b213f4303c780e05d99dBenjamin Kramer  return object_error::success;
5560fcab076f0358890e2f1b213f4303c780e05d99dBenjamin Kramer}
5570fcab076f0358890e2f1b213f4303c780e05d99dBenjamin Kramererror_code COFFObjectFile::getRelocationType(DataRefImpl Rel,
5580fcab076f0358890e2f1b213f4303c780e05d99dBenjamin Kramer                                             uint32_t &Res) const {
5590fcab076f0358890e2f1b213f4303c780e05d99dBenjamin Kramer  const coff_relocation* R = toRel(Rel);
5600fcab076f0358890e2f1b213f4303c780e05d99dBenjamin Kramer  Res = R->Type;
5610fcab076f0358890e2f1b213f4303c780e05d99dBenjamin Kramer  return object_error::success;
5620fcab076f0358890e2f1b213f4303c780e05d99dBenjamin Kramer}
5630fcab076f0358890e2f1b213f4303c780e05d99dBenjamin Kramererror_code COFFObjectFile::getRelocationAdditionalInfo(DataRefImpl Rel,
5640fcab076f0358890e2f1b213f4303c780e05d99dBenjamin Kramer                                                       int64_t &Res) const {
5650fcab076f0358890e2f1b213f4303c780e05d99dBenjamin Kramer  Res = 0;
5660fcab076f0358890e2f1b213f4303c780e05d99dBenjamin Kramer  return object_error::success;
5670fcab076f0358890e2f1b213f4303c780e05d99dBenjamin Kramer}
5680fcab076f0358890e2f1b213f4303c780e05d99dBenjamin KramerObjectFile::relocation_iterator COFFObjectFile::begin_relocations() const {
5690fcab076f0358890e2f1b213f4303c780e05d99dBenjamin Kramer  DataRefImpl ret;
5700fcab076f0358890e2f1b213f4303c780e05d99dBenjamin Kramer  ret.d.a = 0;
5710fcab076f0358890e2f1b213f4303c780e05d99dBenjamin Kramer  ret.d.b = 1;
5720fcab076f0358890e2f1b213f4303c780e05d99dBenjamin Kramer  return relocation_iterator(RelocationRef(ret, this));
5730fcab076f0358890e2f1b213f4303c780e05d99dBenjamin Kramer}
5740fcab076f0358890e2f1b213f4303c780e05d99dBenjamin KramerObjectFile::relocation_iterator COFFObjectFile::end_relocations() const {
5750fcab076f0358890e2f1b213f4303c780e05d99dBenjamin Kramer  DataRefImpl ret;
5760fcab076f0358890e2f1b213f4303c780e05d99dBenjamin Kramer  ret.d.a = 0;
5770fcab076f0358890e2f1b213f4303c780e05d99dBenjamin Kramer  ret.d.b = Header->NumberOfSections;
5780fcab076f0358890e2f1b213f4303c780e05d99dBenjamin Kramer  return relocation_iterator(RelocationRef(ret, this));
5790fcab076f0358890e2f1b213f4303c780e05d99dBenjamin Kramer}
5800fcab076f0358890e2f1b213f4303c780e05d99dBenjamin Kramer
5810fcab076f0358890e2f1b213f4303c780e05d99dBenjamin Kramer
582a1ef8ef66075e28e020e5d2f408e0a9bae9eb9d3Michael J. Spencernamespace llvm {
583a1ef8ef66075e28e020e5d2f408e0a9bae9eb9d3Michael J. Spencer
584a1ef8ef66075e28e020e5d2f408e0a9bae9eb9d3Michael J. Spencer  ObjectFile *ObjectFile::createCOFFObjectFile(MemoryBuffer *Object) {
585001c9205fca2220480589ec355cb6ec701a37e08Michael J. Spencer    error_code ec;
586001c9205fca2220480589ec355cb6ec701a37e08Michael J. Spencer    return new COFFObjectFile(Object, ec);
587a1ef8ef66075e28e020e5d2f408e0a9bae9eb9d3Michael J. Spencer  }
588a1ef8ef66075e28e020e5d2f408e0a9bae9eb9d3Michael J. Spencer
589a1ef8ef66075e28e020e5d2f408e0a9bae9eb9d3Michael J. Spencer} // end namespace llvm
590