1001c9205fca2220480589ec355cb6ec701a37e08Michael J. Spencer//===- COFF.h - COFF object file implementation -----------------*- C++ -*-===// 2001c9205fca2220480589ec355cb6ec701a37e08Michael J. Spencer// 3001c9205fca2220480589ec355cb6ec701a37e08Michael J. Spencer// The LLVM Compiler Infrastructure 4001c9205fca2220480589ec355cb6ec701a37e08Michael J. Spencer// 5001c9205fca2220480589ec355cb6ec701a37e08Michael J. Spencer// This file is distributed under the University of Illinois Open Source 6001c9205fca2220480589ec355cb6ec701a37e08Michael J. Spencer// License. See LICENSE.TXT for details. 7001c9205fca2220480589ec355cb6ec701a37e08Michael J. Spencer// 8001c9205fca2220480589ec355cb6ec701a37e08Michael J. Spencer//===----------------------------------------------------------------------===// 9001c9205fca2220480589ec355cb6ec701a37e08Michael J. Spencer// 10001c9205fca2220480589ec355cb6ec701a37e08Michael J. Spencer// This file declares the COFFObjectFile class. 11001c9205fca2220480589ec355cb6ec701a37e08Michael J. Spencer// 12001c9205fca2220480589ec355cb6ec701a37e08Michael J. Spencer//===----------------------------------------------------------------------===// 13001c9205fca2220480589ec355cb6ec701a37e08Michael J. Spencer 14001c9205fca2220480589ec355cb6ec701a37e08Michael J. Spencer#ifndef LLVM_OBJECT_COFF_H 15001c9205fca2220480589ec355cb6ec701a37e08Michael J. Spencer#define LLVM_OBJECT_COFF_H 16001c9205fca2220480589ec355cb6ec701a37e08Michael J. Spencer 17001c9205fca2220480589ec355cb6ec701a37e08Michael J. Spencer#include "llvm/Object/ObjectFile.h" 18001c9205fca2220480589ec355cb6ec701a37e08Michael J. Spencer#include "llvm/Support/COFF.h" 19001c9205fca2220480589ec355cb6ec701a37e08Michael J. Spencer#include "llvm/Support/Endian.h" 20001c9205fca2220480589ec355cb6ec701a37e08Michael J. Spencer 21001c9205fca2220480589ec355cb6ec701a37e08Michael J. Spencernamespace llvm { 221f6e3f9544c93213111a2f8b314c926c0d0e30e5Michael J. Spencer template <typename T> 231f6e3f9544c93213111a2f8b314c926c0d0e30e5Michael J. Spencer class ArrayRef; 241f6e3f9544c93213111a2f8b314c926c0d0e30e5Michael J. Spencer 25001c9205fca2220480589ec355cb6ec701a37e08Michael J. Spencernamespace object { 26001c9205fca2220480589ec355cb6ec701a37e08Michael J. Spencer 27001c9205fca2220480589ec355cb6ec701a37e08Michael J. Spencerstruct coff_file_header { 28001c9205fca2220480589ec355cb6ec701a37e08Michael J. Spencer support::ulittle16_t Machine; 29001c9205fca2220480589ec355cb6ec701a37e08Michael J. Spencer support::ulittle16_t NumberOfSections; 30001c9205fca2220480589ec355cb6ec701a37e08Michael J. Spencer support::ulittle32_t TimeDateStamp; 31001c9205fca2220480589ec355cb6ec701a37e08Michael J. Spencer support::ulittle32_t PointerToSymbolTable; 32001c9205fca2220480589ec355cb6ec701a37e08Michael J. Spencer support::ulittle32_t NumberOfSymbols; 33001c9205fca2220480589ec355cb6ec701a37e08Michael J. Spencer support::ulittle16_t SizeOfOptionalHeader; 34001c9205fca2220480589ec355cb6ec701a37e08Michael J. Spencer support::ulittle16_t Characteristics; 35001c9205fca2220480589ec355cb6ec701a37e08Michael J. Spencer}; 36001c9205fca2220480589ec355cb6ec701a37e08Michael J. Spencer 37001c9205fca2220480589ec355cb6ec701a37e08Michael J. Spencerstruct coff_symbol { 38001c9205fca2220480589ec355cb6ec701a37e08Michael J. Spencer struct StringTableOffset { 39001c9205fca2220480589ec355cb6ec701a37e08Michael J. Spencer support::ulittle32_t Zeroes; 40001c9205fca2220480589ec355cb6ec701a37e08Michael J. Spencer support::ulittle32_t Offset; 41001c9205fca2220480589ec355cb6ec701a37e08Michael J. Spencer }; 42001c9205fca2220480589ec355cb6ec701a37e08Michael J. Spencer 43001c9205fca2220480589ec355cb6ec701a37e08Michael J. Spencer union { 44001c9205fca2220480589ec355cb6ec701a37e08Michael J. Spencer char ShortName[8]; 45001c9205fca2220480589ec355cb6ec701a37e08Michael J. Spencer StringTableOffset Offset; 46001c9205fca2220480589ec355cb6ec701a37e08Michael J. Spencer } Name; 47001c9205fca2220480589ec355cb6ec701a37e08Michael J. Spencer 48001c9205fca2220480589ec355cb6ec701a37e08Michael J. Spencer support::ulittle32_t Value; 49001c9205fca2220480589ec355cb6ec701a37e08Michael J. Spencer support::little16_t SectionNumber; 50001c9205fca2220480589ec355cb6ec701a37e08Michael J. Spencer 515e3a082c797f0214d44858b05a13543872dfd413Michael J. Spencer support::ulittle16_t Type; 52001c9205fca2220480589ec355cb6ec701a37e08Michael J. Spencer 53001c9205fca2220480589ec355cb6ec701a37e08Michael J. Spencer support::ulittle8_t StorageClass; 54001c9205fca2220480589ec355cb6ec701a37e08Michael J. Spencer support::ulittle8_t NumberOfAuxSymbols; 555e3a082c797f0214d44858b05a13543872dfd413Michael J. Spencer 565e3a082c797f0214d44858b05a13543872dfd413Michael J. Spencer uint8_t getBaseType() const { 575e3a082c797f0214d44858b05a13543872dfd413Michael J. Spencer return Type & 0x0F; 585e3a082c797f0214d44858b05a13543872dfd413Michael J. Spencer } 595e3a082c797f0214d44858b05a13543872dfd413Michael J. Spencer 605e3a082c797f0214d44858b05a13543872dfd413Michael J. Spencer uint8_t getComplexType() const { 615e3a082c797f0214d44858b05a13543872dfd413Michael J. Spencer return (Type & 0xF0) >> 4; 625e3a082c797f0214d44858b05a13543872dfd413Michael J. Spencer } 63001c9205fca2220480589ec355cb6ec701a37e08Michael J. Spencer}; 64001c9205fca2220480589ec355cb6ec701a37e08Michael J. Spencer 65001c9205fca2220480589ec355cb6ec701a37e08Michael J. Spencerstruct coff_section { 66001c9205fca2220480589ec355cb6ec701a37e08Michael J. Spencer char Name[8]; 67001c9205fca2220480589ec355cb6ec701a37e08Michael J. Spencer support::ulittle32_t VirtualSize; 68001c9205fca2220480589ec355cb6ec701a37e08Michael J. Spencer support::ulittle32_t VirtualAddress; 69001c9205fca2220480589ec355cb6ec701a37e08Michael J. Spencer support::ulittle32_t SizeOfRawData; 70001c9205fca2220480589ec355cb6ec701a37e08Michael J. Spencer support::ulittle32_t PointerToRawData; 71001c9205fca2220480589ec355cb6ec701a37e08Michael J. Spencer support::ulittle32_t PointerToRelocations; 72001c9205fca2220480589ec355cb6ec701a37e08Michael J. Spencer support::ulittle32_t PointerToLinenumbers; 73001c9205fca2220480589ec355cb6ec701a37e08Michael J. Spencer support::ulittle16_t NumberOfRelocations; 74001c9205fca2220480589ec355cb6ec701a37e08Michael J. Spencer support::ulittle16_t NumberOfLinenumbers; 75001c9205fca2220480589ec355cb6ec701a37e08Michael J. Spencer support::ulittle32_t Characteristics; 76001c9205fca2220480589ec355cb6ec701a37e08Michael J. Spencer}; 77001c9205fca2220480589ec355cb6ec701a37e08Michael J. Spencer 780fcab076f0358890e2f1b213f4303c780e05d99dBenjamin Kramerstruct coff_relocation { 790fcab076f0358890e2f1b213f4303c780e05d99dBenjamin Kramer support::ulittle32_t VirtualAddress; 800fcab076f0358890e2f1b213f4303c780e05d99dBenjamin Kramer support::ulittle32_t SymbolTableIndex; 810fcab076f0358890e2f1b213f4303c780e05d99dBenjamin Kramer support::ulittle16_t Type; 820fcab076f0358890e2f1b213f4303c780e05d99dBenjamin Kramer}; 830fcab076f0358890e2f1b213f4303c780e05d99dBenjamin Kramer 840e752cb4b4eb5676aace4d9f3d7c2e2334c13777Michael J. Spencerstruct coff_aux_section_definition { 850e752cb4b4eb5676aace4d9f3d7c2e2334c13777Michael J. Spencer support::ulittle32_t Length; 860e752cb4b4eb5676aace4d9f3d7c2e2334c13777Michael J. Spencer support::ulittle16_t NumberOfRelocations; 870e752cb4b4eb5676aace4d9f3d7c2e2334c13777Michael J. Spencer support::ulittle16_t NumberOfLinenumbers; 880e752cb4b4eb5676aace4d9f3d7c2e2334c13777Michael J. Spencer support::ulittle32_t CheckSum; 890e752cb4b4eb5676aace4d9f3d7c2e2334c13777Michael J. Spencer support::ulittle16_t Number; 900e752cb4b4eb5676aace4d9f3d7c2e2334c13777Michael J. Spencer support::ulittle8_t Selection; 910e752cb4b4eb5676aace4d9f3d7c2e2334c13777Michael J. Spencer char Unused[3]; 920e752cb4b4eb5676aace4d9f3d7c2e2334c13777Michael J. Spencer}; 930e752cb4b4eb5676aace4d9f3d7c2e2334c13777Michael J. Spencer 94001c9205fca2220480589ec355cb6ec701a37e08Michael J. Spencerclass COFFObjectFile : public ObjectFile { 95001c9205fca2220480589ec355cb6ec701a37e08Michael J. Spencerprivate: 96001c9205fca2220480589ec355cb6ec701a37e08Michael J. Spencer const coff_file_header *Header; 97001c9205fca2220480589ec355cb6ec701a37e08Michael J. Spencer const coff_section *SectionTable; 98001c9205fca2220480589ec355cb6ec701a37e08Michael J. Spencer const coff_symbol *SymbolTable; 99001c9205fca2220480589ec355cb6ec701a37e08Michael J. Spencer const char *StringTable; 10025b15777df42d5d608810f6881b6c98107481d69Michael J. Spencer uint32_t StringTableSize; 101001c9205fca2220480589ec355cb6ec701a37e08Michael J. Spencer 10225b15777df42d5d608810f6881b6c98107481d69Michael J. Spencer error_code getString(uint32_t offset, StringRef &Res) const; 10325b15777df42d5d608810f6881b6c98107481d69Michael J. Spencer 10425b15777df42d5d608810f6881b6c98107481d69Michael J. Spencer const coff_symbol *toSymb(DataRefImpl Symb) const; 10525b15777df42d5d608810f6881b6c98107481d69Michael J. Spencer const coff_section *toSec(DataRefImpl Sec) const; 1060fcab076f0358890e2f1b213f4303c780e05d99dBenjamin Kramer const coff_relocation *toRel(DataRefImpl Rel) const; 107001c9205fca2220480589ec355cb6ec701a37e08Michael J. Spencer 108001c9205fca2220480589ec355cb6ec701a37e08Michael J. Spencerprotected: 10925b15777df42d5d608810f6881b6c98107481d69Michael J. Spencer virtual error_code getSymbolNext(DataRefImpl Symb, SymbolRef &Res) const; 11025b15777df42d5d608810f6881b6c98107481d69Michael J. Spencer virtual error_code getSymbolName(DataRefImpl Symb, StringRef &Res) const; 111b0436a73054fe676b216a0cf872d1fc433125c62Danil Malyshev virtual error_code getSymbolFileOffset(DataRefImpl Symb, uint64_t &Res) const; 11225b15777df42d5d608810f6881b6c98107481d69Michael J. Spencer virtual error_code getSymbolAddress(DataRefImpl Symb, uint64_t &Res) const; 11325b15777df42d5d608810f6881b6c98107481d69Michael J. Spencer virtual error_code getSymbolSize(DataRefImpl Symb, uint64_t &Res) const; 11425b15777df42d5d608810f6881b6c98107481d69Michael J. Spencer virtual error_code getSymbolNMTypeChar(DataRefImpl Symb, char &Res) const; 115c46255a32ec92c427e621b6d7eabd887962ce4a4David Meyer virtual error_code getSymbolFlags(DataRefImpl Symb, uint32_t &Res) const; 1161130a799ab2fd7042625163a2506518960394884Michael J. Spencer virtual error_code getSymbolType(DataRefImpl Symb, SymbolRef::Type &Res) const; 1179b2b812fea4df160437e7b7d56e38f6335189ad0Michael J. Spencer virtual error_code getSymbolSection(DataRefImpl Symb, 1189b2b812fea4df160437e7b7d56e38f6335189ad0Michael J. Spencer section_iterator &Res) const; 11925b15777df42d5d608810f6881b6c98107481d69Michael J. Spencer 12025b15777df42d5d608810f6881b6c98107481d69Michael J. Spencer virtual error_code getSectionNext(DataRefImpl Sec, SectionRef &Res) const; 12125b15777df42d5d608810f6881b6c98107481d69Michael J. Spencer virtual error_code getSectionName(DataRefImpl Sec, StringRef &Res) const; 12225b15777df42d5d608810f6881b6c98107481d69Michael J. Spencer virtual error_code getSectionAddress(DataRefImpl Sec, uint64_t &Res) const; 12325b15777df42d5d608810f6881b6c98107481d69Michael J. Spencer virtual error_code getSectionSize(DataRefImpl Sec, uint64_t &Res) const; 12425b15777df42d5d608810f6881b6c98107481d69Michael J. Spencer virtual error_code getSectionContents(DataRefImpl Sec, StringRef &Res) const; 125e2f2f07be7cf2b55b7e5501291bbcede87e43fd6Michael J. Spencer virtual error_code getSectionAlignment(DataRefImpl Sec, uint64_t &Res) const; 12625b15777df42d5d608810f6881b6c98107481d69Michael J. Spencer virtual error_code isSectionText(DataRefImpl Sec, bool &Res) const; 12713afc5eff2d7370ab486d5039886ab8bbf9039daMichael J. Spencer virtual error_code isSectionData(DataRefImpl Sec, bool &Res) const; 12813afc5eff2d7370ab486d5039886ab8bbf9039daMichael J. Spencer virtual error_code isSectionBSS(DataRefImpl Sec, bool &Res) const; 129c68dda815e64fb2fb463318d1eaa304e22199d50Preston Gurd virtual error_code isSectionVirtual(DataRefImpl Sec, bool &Res) const; 130c68dda815e64fb2fb463318d1eaa304e22199d50Preston Gurd virtual error_code isSectionZeroInit(DataRefImpl Sec, bool &Res) const; 131c68dda815e64fb2fb463318d1eaa304e22199d50Preston Gurd virtual error_code isSectionRequiredForExecution(DataRefImpl Sec, 132c68dda815e64fb2fb463318d1eaa304e22199d50Preston Gurd bool &Res) const; 13307ea23aa2d17f701fa125442c20c1eba75b55fdbBenjamin Kramer virtual error_code sectionContainsSymbol(DataRefImpl Sec, DataRefImpl Symb, 13407ea23aa2d17f701fa125442c20c1eba75b55fdbBenjamin Kramer bool &Result) const; 1354344b1ef9b3721a5ebc2e024f753772a1e4ddd92Michael J. Spencer virtual relocation_iterator getSectionRelBegin(DataRefImpl Sec) const; 1364344b1ef9b3721a5ebc2e024f753772a1e4ddd92Michael J. Spencer virtual relocation_iterator getSectionRelEnd(DataRefImpl Sec) const; 137001c9205fca2220480589ec355cb6ec701a37e08Michael J. Spencer 1380fcab076f0358890e2f1b213f4303c780e05d99dBenjamin Kramer virtual error_code getRelocationNext(DataRefImpl Rel, 1390fcab076f0358890e2f1b213f4303c780e05d99dBenjamin Kramer RelocationRef &Res) const; 1400fcab076f0358890e2f1b213f4303c780e05d99dBenjamin Kramer virtual error_code getRelocationAddress(DataRefImpl Rel, 1410fcab076f0358890e2f1b213f4303c780e05d99dBenjamin Kramer uint64_t &Res) const; 142b0436a73054fe676b216a0cf872d1fc433125c62Danil Malyshev virtual error_code getRelocationOffset(DataRefImpl Rel, 143b0436a73054fe676b216a0cf872d1fc433125c62Danil Malyshev uint64_t &Res) const; 1440fcab076f0358890e2f1b213f4303c780e05d99dBenjamin Kramer virtual error_code getRelocationSymbol(DataRefImpl Rel, 1450fcab076f0358890e2f1b213f4303c780e05d99dBenjamin Kramer SymbolRef &Res) const; 1460fcab076f0358890e2f1b213f4303c780e05d99dBenjamin Kramer virtual error_code getRelocationType(DataRefImpl Rel, 1479472b8d220fc746498429f430cb4c4dbfbd38f2aOwen Anderson uint64_t &Res) const; 1484344b1ef9b3721a5ebc2e024f753772a1e4ddd92Michael J. Spencer virtual error_code getRelocationTypeName(DataRefImpl Rel, 1494344b1ef9b3721a5ebc2e024f753772a1e4ddd92Michael J. Spencer SmallVectorImpl<char> &Result) const; 1500fcab076f0358890e2f1b213f4303c780e05d99dBenjamin Kramer virtual error_code getRelocationAdditionalInfo(DataRefImpl Rel, 1510fcab076f0358890e2f1b213f4303c780e05d99dBenjamin Kramer int64_t &Res) const; 1524344b1ef9b3721a5ebc2e024f753772a1e4ddd92Michael J. Spencer virtual error_code getRelocationValueString(DataRefImpl Rel, 1534344b1ef9b3721a5ebc2e024f753772a1e4ddd92Michael J. Spencer SmallVectorImpl<char> &Result) const; 1544344b1ef9b3721a5ebc2e024f753772a1e4ddd92Michael J. Spencer 1555c2b4ea73c8f48bb5f96c86fe437385b8fb3dcdaDavid Meyer virtual error_code getLibraryNext(DataRefImpl LibData, 1565c2b4ea73c8f48bb5f96c86fe437385b8fb3dcdaDavid Meyer LibraryRef &Result) const; 1575c2b4ea73c8f48bb5f96c86fe437385b8fb3dcdaDavid Meyer virtual error_code getLibraryPath(DataRefImpl LibData, 1585c2b4ea73c8f48bb5f96c86fe437385b8fb3dcdaDavid Meyer StringRef &Result) const; 1595c2b4ea73c8f48bb5f96c86fe437385b8fb3dcdaDavid Meyer 160001c9205fca2220480589ec355cb6ec701a37e08Michael J. Spencerpublic: 161001c9205fca2220480589ec355cb6ec701a37e08Michael J. Spencer COFFObjectFile(MemoryBuffer *Object, error_code &ec); 162001c9205fca2220480589ec355cb6ec701a37e08Michael J. Spencer virtual symbol_iterator begin_symbols() const; 163001c9205fca2220480589ec355cb6ec701a37e08Michael J. Spencer virtual symbol_iterator end_symbols() const; 164dfa1896b6b61e708f002b814794890ff308172eeMichael J. Spencer virtual symbol_iterator begin_dynamic_symbols() const; 165dfa1896b6b61e708f002b814794890ff308172eeMichael J. Spencer virtual symbol_iterator end_dynamic_symbols() const; 1665c2b4ea73c8f48bb5f96c86fe437385b8fb3dcdaDavid Meyer virtual library_iterator begin_libraries_needed() const; 1675c2b4ea73c8f48bb5f96c86fe437385b8fb3dcdaDavid Meyer virtual library_iterator end_libraries_needed() const; 168001c9205fca2220480589ec355cb6ec701a37e08Michael J. Spencer virtual section_iterator begin_sections() const; 169001c9205fca2220480589ec355cb6ec701a37e08Michael J. Spencer virtual section_iterator end_sections() const; 170001c9205fca2220480589ec355cb6ec701a37e08Michael J. Spencer 171d4d03e09d3686d317da1166b578ca5ca35593970Marshall Clow const coff_section *getCOFFSection(section_iterator &It) const; 172d4d03e09d3686d317da1166b578ca5ca35593970Marshall Clow const coff_symbol *getCOFFSymbol(symbol_iterator &It) const; 1739ac0f1d7255d7941c331b0a62a830a3b033358fdMarshall Clow const coff_relocation *getCOFFRelocation(relocation_iterator &It) const; 1749ac0f1d7255d7941c331b0a62a830a3b033358fdMarshall Clow 175001c9205fca2220480589ec355cb6ec701a37e08Michael J. Spencer virtual uint8_t getBytesInAddress() const; 176001c9205fca2220480589ec355cb6ec701a37e08Michael J. Spencer virtual StringRef getFileFormatName() const; 177001c9205fca2220480589ec355cb6ec701a37e08Michael J. Spencer virtual unsigned getArch() const; 17897f7787bfb56ad31fe20ec0bb9c3c9f3253d14fbDavid Meyer virtual StringRef getLoadName() const; 179ab6bcf35aefe823894d349773ebd53f465f122b7Michael J. Spencer 1800e752cb4b4eb5676aace4d9f3d7c2e2334c13777Michael J. Spencer error_code getHeader(const coff_file_header *&Res) const; 1810e752cb4b4eb5676aace4d9f3d7c2e2334c13777Michael J. Spencer error_code getSection(int32_t index, const coff_section *&Res) const; 1820e752cb4b4eb5676aace4d9f3d7c2e2334c13777Michael J. Spencer error_code getSymbol(uint32_t index, const coff_symbol *&Res) const; 1830e752cb4b4eb5676aace4d9f3d7c2e2334c13777Michael J. Spencer template <typename T> 1840e752cb4b4eb5676aace4d9f3d7c2e2334c13777Michael J. Spencer error_code getAuxSymbol(uint32_t index, const T *&Res) const { 1850e752cb4b4eb5676aace4d9f3d7c2e2334c13777Michael J. Spencer const coff_symbol *s; 1860e752cb4b4eb5676aace4d9f3d7c2e2334c13777Michael J. Spencer error_code ec = getSymbol(index, s); 1870e752cb4b4eb5676aace4d9f3d7c2e2334c13777Michael J. Spencer Res = reinterpret_cast<const T*>(s); 1880e752cb4b4eb5676aace4d9f3d7c2e2334c13777Michael J. Spencer return ec; 1890e752cb4b4eb5676aace4d9f3d7c2e2334c13777Michael J. Spencer } 1900e752cb4b4eb5676aace4d9f3d7c2e2334c13777Michael J. Spencer error_code getSymbolName(const coff_symbol *symbol, StringRef &Res) const; 191d4d03e09d3686d317da1166b578ca5ca35593970Marshall Clow ArrayRef<uint8_t> getSymbolAuxData(const coff_symbol *symbol) const; 192d4d03e09d3686d317da1166b578ca5ca35593970Marshall Clow 193b35a896e072ff46c38905419b7f55aaccdb1d702Michael J. Spencer error_code getSectionName(const coff_section *Sec, StringRef &Res) const; 1941f6e3f9544c93213111a2f8b314c926c0d0e30e5Michael J. Spencer error_code getSectionContents(const coff_section *Sec, 1951f6e3f9544c93213111a2f8b314c926c0d0e30e5Michael J. Spencer ArrayRef<uint8_t> &Res) const; 196ab6bcf35aefe823894d349773ebd53f465f122b7Michael J. Spencer 197ab6bcf35aefe823894d349773ebd53f465f122b7Michael J. Spencer static inline bool classof(const Binary *v) { 1986f9489a86f33624f9ff5388411d12359ce9cef20David Meyer return v->isCOFF(); 199ab6bcf35aefe823894d349773ebd53f465f122b7Michael J. Spencer } 200ab6bcf35aefe823894d349773ebd53f465f122b7Michael J. Spencer static inline bool classof(const COFFObjectFile *v) { return true; } 201001c9205fca2220480589ec355cb6ec701a37e08Michael J. Spencer}; 202001c9205fca2220480589ec355cb6ec701a37e08Michael J. Spencer 203001c9205fca2220480589ec355cb6ec701a37e08Michael J. Spencer} 204001c9205fca2220480589ec355cb6ec701a37e08Michael J. Spencer} 205001c9205fca2220480589ec355cb6ec701a37e08Michael J. Spencer 206001c9205fca2220480589ec355cb6ec701a37e08Michael J. Spencer#endif 207