[llvm-commits] PATCH: add new test tool: obj2yaml
Michael Spencer
bigcheesegs at gmail.com
Sat Jun 9 02:44:51 PDT 2012
On Fri, Jun 8, 2012 at 11:09 AM, Marshall Clow <mclow.lists at gmail.com> wrote:
> [ resending to llvm-commits instead of -dev ]
>
> This patch adds a tool called 'obj2yaml', which takes an object file, and produces a YAML representation of the file.
> This is a companion tool to Michael Spencer's proposed "yaml2obj" tool.
>
> This tool processes only COFF files; the plan is to enhance it to handle other object formats, as well as object archives.
> The primary uses for this tool is expected to be:
> 1) Debugging object files that are produced by llvm and lld.
> 2) Automated testing suites.
>
> The goal is to have obj2yaml and yaml2obj be inverse operations, so that one can test either by using the other.
> So, both obj -> yaml -> obj and yaml -> obj -> yaml are expected to be idempotent.
>
> -- Marshall
>
> Marshall Clow Idio Software <mailto:mclow.lists at gmail.com>
>
> A.D. 1517: Martin Luther nails his 95 Theses to the church door and is promptly moderated down to (-1, Flamebait).
> -- Yu Suzuki
The design looks good, however there are quite a few LLVM style issues. The
major one that applies everywhere is that we use 2 spaces instead of tabs.
http://llvm.org/docs/CodingStandards.html#scf_spacestabs
Remaining comments are inline.
Index: utils/obj2yaml/obj2yaml.cpp
===================================================================
--- utils/obj2yaml/obj2yaml.cpp (revision 0)
+++ utils/obj2yaml/obj2yaml.cpp (revision 0)
@@ -0,0 +1,509 @@
+#include "llvm/ADT/OwningPtr.h"
+
+#include "llvm/Support/system_error.h"
+#include "llvm/Support/COFF.h"
+#include "llvm/Support/Endian.h"
+#include "llvm/Support/CommandLine.h"
+#include "llvm/Support/PrettyStackTrace.h"
+#include "llvm/Support/Signals.h"
+#include "llvm/Support/ManagedStatic.h"
+#include "llvm/Support/MemoryBuffer.h"
+
+#include "llvm/Object/Archive.h"
+
+#include <stdexcept>
No exceptions. http://llvm.org/docs/CodingStandards.html#ci_rtti_exceptions
+#include <fstream>
+#include <iostream>
http://llvm.org/docs/CodingStandards.html#ll_iostream
+#include <vector>
+#include <map>
+#include <cassert>
+#include <utility>
The includes are grouped correctly, but they should be sorted alphabetically
within each group. http://llvm.org/docs/CodingStandards.html#scf_includes
+// Utility bits
+#define ArrSize(x) (sizeof(x)/sizeof(x[0]))
We have array_lengthof in ADT/STLExtras.h
+
+unsigned char printable ( unsigned char ch ) {
There should not be a space between printable and (. There should also not be
a space directly after ( and before ).
http://llvm.org/docs/CodingStandards.html#micro_spaceparen
Also all variables should start with an uppercase letter.
http://llvm.org/docs/CodingStandards.html#ll_naming
+ return ch >= ' ' && ch <= '~' ? ch : '.';
+ }
The } should not be indented.
+std::ostream& yaml_hex_stream ( std::ostream &out, const char *prefix,
This should be using raw_ostream.
http://llvm.org/docs/CodingStandards.html#ll_raw_ostream
This should be yamlHexStream.
http://llvm.org/docs/CodingStandards.html#ll_naming
Also the & should be on the right.
+ const unsigned char *data, std::size_t length ) {
+ const char *hex = "0123456789ABCDEF";
+ out << prefix << " !hex \"";
+ const unsigned char *p = data;
+ std::size_t len = length;
+ while ( len-- > 0 ) {
+ out << hex[( *p >> 4 ) & 0x0F] << hex[( *p & 0x0F )];
+ p++;
+ }
+
+ out << "\" # |";
+ p = data;
+ len = length;
+ while ( len-- > 0 )
+ out << printable ( *p++ );
+ out << "|" << std::endl;
+
+ return out;
+ }
+
+std::ostream& yaml_name ( std::ostream &out, const char *name,
std::size_t name_size ) {
80 colums. http://llvm.org/docs/CodingStandards.html#scf_codewidth
+ for ( std::size_t i = 0; i < name_size; ++i ) {
+ if ( !name[i] ) break;
+ out << name[i];
+ }
+ return out;
+ }
+
+template<typename T>
+T pointer_offset_cast ( T p, std::size_t offset ) {
+ return reinterpret_cast<T> ( reinterpret_cast<const char *> ( p ) + offset );
+}
+
+// Given a map of <enum, const char *>, look up a value
+template <typename T>
+const char *name_lookup ( const std::map<T, const char *> &m, int val,
+ const char *not_found = NULL ) {
+ typename std::map<T, const char *>::const_iterator it
+ = m.find ( static_cast<T> ( val ));
+ return it != m.end () ? it->second : not_found;
+ }
+
+
+namespace coff2yaml {
The content of a namespace should not be indented when it is this large.
http://llvm.org/docs/CodingStandards.html#micro_namespaceindent
+ using namespace llvm::COFF;
+
+ enum {
+ OptionalHeaderSize = 28
+ };
+
+ template <typename One, typename Two>
+ struct my_pair {
+ One first;
+ Two second;
+ };
+
+ #define string_pair(x) {x, #x}
Macros should be all uppercase. Although this has such a small scope I'm not
sure it matters.
+ static const my_pair<MachineTypes, const char *>
+ MachineTypePairs [] = {
+ string_pair(IMAGE_FILE_MACHINE_UNKNOWN),
+ string_pair(IMAGE_FILE_MACHINE_AM33),
+ string_pair(IMAGE_FILE_MACHINE_AMD64),
+ string_pair(IMAGE_FILE_MACHINE_ARM),
+ string_pair(IMAGE_FILE_MACHINE_ARMV7),
+ string_pair(IMAGE_FILE_MACHINE_EBC),
+ string_pair(IMAGE_FILE_MACHINE_I386),
+ string_pair(IMAGE_FILE_MACHINE_IA64),
+ string_pair(IMAGE_FILE_MACHINE_M32R),
+ string_pair(IMAGE_FILE_MACHINE_MIPS16),
+ string_pair(IMAGE_FILE_MACHINE_MIPSFPU),
+ string_pair(IMAGE_FILE_MACHINE_MIPSFPU16),
+ string_pair(IMAGE_FILE_MACHINE_POWERPC),
+ string_pair(IMAGE_FILE_MACHINE_POWERPCFP),
+ string_pair(IMAGE_FILE_MACHINE_R4000),
+ string_pair(IMAGE_FILE_MACHINE_SH3),
+ string_pair(IMAGE_FILE_MACHINE_SH3DSP),
+ string_pair(IMAGE_FILE_MACHINE_SH4),
+ string_pair(IMAGE_FILE_MACHINE_SH5),
+ string_pair(IMAGE_FILE_MACHINE_THUMB),
+ string_pair(IMAGE_FILE_MACHINE_WCEMIPSV2)
+ };
+
+ static const my_pair<SectionCharacteristics, const char *>
+ SectionCharacteristicsPairs1 [] = {
+ string_pair(IMAGE_SCN_TYPE_NO_PAD),
+ string_pair(IMAGE_SCN_CNT_CODE),
+ string_pair(IMAGE_SCN_CNT_INITIALIZED_DATA),
+ string_pair(IMAGE_SCN_CNT_UNINITIALIZED_DATA),
+ string_pair(IMAGE_SCN_LNK_OTHER),
+ string_pair(IMAGE_SCN_LNK_INFO),
+ string_pair(IMAGE_SCN_LNK_REMOVE),
+ string_pair(IMAGE_SCN_LNK_COMDAT),
+ string_pair(IMAGE_SCN_GPREL),
+ string_pair(IMAGE_SCN_MEM_PURGEABLE),
+ string_pair(IMAGE_SCN_MEM_16BIT),
+ string_pair(IMAGE_SCN_MEM_LOCKED),
+ string_pair(IMAGE_SCN_MEM_PRELOAD)
+ };
+
+ static const my_pair<SectionCharacteristics, const char *>
+ SectionCharacteristicsPairsAlignment [] = {
+ string_pair(IMAGE_SCN_ALIGN_1BYTES),
+ string_pair(IMAGE_SCN_ALIGN_2BYTES),
+ string_pair(IMAGE_SCN_ALIGN_4BYTES),
+ string_pair(IMAGE_SCN_ALIGN_8BYTES),
+ string_pair(IMAGE_SCN_ALIGN_16BYTES),
+ string_pair(IMAGE_SCN_ALIGN_32BYTES),
+ string_pair(IMAGE_SCN_ALIGN_64BYTES),
+ string_pair(IMAGE_SCN_ALIGN_128BYTES),
+ string_pair(IMAGE_SCN_ALIGN_256BYTES),
+ string_pair(IMAGE_SCN_ALIGN_512BYTES),
+ string_pair(IMAGE_SCN_ALIGN_1024BYTES),
+ string_pair(IMAGE_SCN_ALIGN_2048BYTES),
+ string_pair(IMAGE_SCN_ALIGN_4096BYTES),
+ string_pair(IMAGE_SCN_ALIGN_8192BYTES)
+ };
+
+ static const my_pair<SectionCharacteristics, const char *>
+ SectionCharacteristicsPairs2 [] = {
+ string_pair(IMAGE_SCN_LNK_NRELOC_OVFL),
+ string_pair(IMAGE_SCN_MEM_DISCARDABLE),
+ string_pair(IMAGE_SCN_MEM_NOT_CACHED),
+ string_pair(IMAGE_SCN_MEM_NOT_PAGED),
+ string_pair(IMAGE_SCN_MEM_SHARED),
+ string_pair(IMAGE_SCN_MEM_EXECUTE),
+ string_pair(IMAGE_SCN_MEM_READ),
+ string_pair(IMAGE_SCN_MEM_WRITE)
+ };
+
+ static const my_pair<SymbolBaseType, const char *>
+ SymbolBaseTypePairs [] = {
+ string_pair(IMAGE_SYM_TYPE_NULL),
+ string_pair(IMAGE_SYM_TYPE_VOID),
+ string_pair(IMAGE_SYM_TYPE_CHAR),
+ string_pair(IMAGE_SYM_TYPE_SHORT),
+ string_pair(IMAGE_SYM_TYPE_INT),
+ string_pair(IMAGE_SYM_TYPE_LONG),
+ string_pair(IMAGE_SYM_TYPE_FLOAT),
+ string_pair(IMAGE_SYM_TYPE_DOUBLE),
+ string_pair(IMAGE_SYM_TYPE_STRUCT),
+ string_pair(IMAGE_SYM_TYPE_UNION),
+ string_pair(IMAGE_SYM_TYPE_ENUM),
+ string_pair(IMAGE_SYM_TYPE_MOE),
+ string_pair(IMAGE_SYM_TYPE_BYTE),
+ string_pair(IMAGE_SYM_TYPE_WORD),
+ string_pair(IMAGE_SYM_TYPE_UINT),
+ string_pair(IMAGE_SYM_TYPE_DWORD)
+ };
+
+ static const my_pair<SymbolComplexType, const char *>
+ SymbolComplexTypePairs [] = {
+ string_pair(IMAGE_SYM_DTYPE_NULL),
+ string_pair(IMAGE_SYM_DTYPE_POINTER),
+ string_pair(IMAGE_SYM_DTYPE_FUNCTION),
+ string_pair(IMAGE_SYM_DTYPE_ARRAY),
+ };
+
+ static const my_pair<SymbolStorageClass, const char *>
+ SymbolStorageClassPairs [] = {
+ string_pair(IMAGE_SYM_CLASS_END_OF_FUNCTION),
+ string_pair(IMAGE_SYM_CLASS_NULL),
+ string_pair(IMAGE_SYM_CLASS_AUTOMATIC),
+ string_pair(IMAGE_SYM_CLASS_EXTERNAL),
+ string_pair(IMAGE_SYM_CLASS_STATIC),
+ string_pair(IMAGE_SYM_CLASS_REGISTER),
+ string_pair(IMAGE_SYM_CLASS_EXTERNAL_DEF),
+ string_pair(IMAGE_SYM_CLASS_LABEL),
+ string_pair(IMAGE_SYM_CLASS_UNDEFINED_LABEL),
+ string_pair(IMAGE_SYM_CLASS_MEMBER_OF_STRUCT),
+ string_pair(IMAGE_SYM_CLASS_ARGUMENT),
+ string_pair(IMAGE_SYM_CLASS_STRUCT_TAG),
+ string_pair(IMAGE_SYM_CLASS_MEMBER_OF_UNION),
+ string_pair(IMAGE_SYM_CLASS_UNION_TAG),
+ string_pair(IMAGE_SYM_CLASS_TYPE_DEFINITION),
+ string_pair(IMAGE_SYM_CLASS_UNDEFINED_STATIC),
+ string_pair(IMAGE_SYM_CLASS_ENUM_TAG),
+ string_pair(IMAGE_SYM_CLASS_MEMBER_OF_ENUM),
+ string_pair(IMAGE_SYM_CLASS_REGISTER_PARAM),
+ string_pair(IMAGE_SYM_CLASS_BIT_FIELD),
+ string_pair(IMAGE_SYM_CLASS_BLOCK),
+ string_pair(IMAGE_SYM_CLASS_FUNCTION),
+ string_pair(IMAGE_SYM_CLASS_END_OF_STRUCT),
+ string_pair(IMAGE_SYM_CLASS_FILE),
+ string_pair(IMAGE_SYM_CLASS_SECTION),
+ string_pair(IMAGE_SYM_CLASS_WEAK_EXTERNAL),
+ string_pair(IMAGE_SYM_CLASS_CLR_TOKEN),
+ };
+
+ #undef string_pair
+
+ class obj2yaml {
+ public:
+
+ obj2yaml ( const char *contents, std::size_t size );
+ ~obj2yaml () {}
+
+ bool is_valid () const { return valid_; }
+ std::string error_message () const { return error_ ; }
+ std::ostream & write_yaml ( std::ostream &out ); // write the YAML
+ private:
+ // Not implemented bits
+ obj2yaml (); // default constructor
+ obj2yaml ( const obj2yaml & rhs ); // copy constructor
+ obj2yaml & operator = ( const obj2yaml & rhs ); // assignment
+
+ std::ostream& write_symbols ( std::ostream &out,
+ const symbol *symbols, std::size_t numSymbols );
+
+ std::ostream& write_section ( std::ostream &out, const section §,
+ const unsigned char *sectionData, std::size_t sectionDataLength,
+ const relocation *relocations, std::size_t numRelocations );
+
+ template <typename T>
+ T offset_cast ( std::size_t offset ) {
+ return reinterpret_cast<T> ( data_ + offset );
+ }
+
+ const char * data_; // the data we're parsing
+ const std::size_t data_size_; // size of the data
+ bool valid_;
+ std::string error_; // if we failed to validate, what happened
+ const header * header_; // the file header
+ std::vector<section> section_headers_;
+ std::size_t string_table_size_;
+ const char *string_table_;
+
+ // Maps for lookup
+ static bool maps_made;
+ static std::map<MachineTypes, const char *> MachineTypeNames;
+ static std::map<SectionCharacteristics, const char *>
SectionCharacteristicNamesAlignment;
+ static std::map<SymbolBaseType, const char *> SymbolBaseTypeNames;
+ static std::map<SymbolComplexType, const char *> SymbolComplexTypeNames;
+ static std::map<SymbolStorageClass, const char *> SymbolStorageClassNames;
+
+ static void make_maps ();
+ };
+
+ bool obj2yaml::maps_made = false;
+ std::map<MachineTypes, const char *> obj2yaml::MachineTypeNames;
+ std::map<SectionCharacteristics, const char *>
obj2yaml::SectionCharacteristicNamesAlignment;
+ std::map<SymbolBaseType, const char *> obj2yaml::SymbolBaseTypeNames;
+ std::map<SymbolComplexType, const char *>
obj2yaml::SymbolComplexTypeNames;
+ std::map<SymbolStorageClass, const char *>
obj2yaml::SymbolStorageClassNames;
+
+// Build a map from a sequence of pairs
+ template<typename T>
+ void build_map ( std::map<T, const char *> &m,
+ const my_pair<T, const char *> *ptr, std::size_t count ) {
+ for ( std::size_t i = 0; i < count; ++i, ptr++ )
+ m [ ptr->first ] = ptr->second;
+ }
+
+ void obj2yaml::make_maps () {
+ // I'd rather that these were static_assert
+ assert ( sizeof ( header ) == HeaderSize );
+ assert ( sizeof ( section ) == SectionSize );
+ // Using clang on MacOS, these are not true
This is bad.
+ // assert ( sizeof ( symbol ) == SymbolSize );
+ // assert ( sizeof ( relocation ) == RelocationSize );
+
+ build_map ( MachineTypeNames,
+ MachineTypePairs, ArrSize(MachineTypePairs));
+ build_map ( SectionCharacteristicNamesAlignment,
+ SectionCharacteristicsPairsAlignment,
+ ArrSize(SectionCharacteristicsPairsAlignment));
+ build_map ( SymbolBaseTypeNames,
+ SymbolBaseTypePairs, ArrSize(SymbolBaseTypePairs));
+ build_map ( SymbolComplexTypeNames,
+ SymbolComplexTypePairs, ArrSize(SymbolComplexTypePairs));
+ build_map ( SymbolStorageClassNames,
+ SymbolStorageClassPairs, ArrSize(SymbolStorageClassPairs));
+
+ maps_made = true;
+ }
+
+/*
+ My preferred solution here would be to throw a std::runtime_error that
+ contained the string describing the error that occurred. However, exceptions
+ are disabled in llvm code. So, instead, we just set a boolean 'is_valid' and
+ save the error message for the client to retrieve.
+ In any case, the object is always left in a destructible state.
+*/
+ obj2yaml::obj2yaml ( const char *contents, std::size_t size ) :
+ data_ ( contents ), data_size_ ( size ),
+ valid_ ( false ), string_table_size_(0), string_table_ (NULL) {
+
+ // One time init; not thread safe
+ if ( !maps_made )
+ make_maps ();
+
+ if ( data_size_ < HeaderSize )
+ { error_ = "File too small" ; return ; }
+
+ // validate the header
+ header_ = offset_cast<const header *> ( 0 ); // header is at the start
+ if ( header_->SizeOfOptionalHeader != 0
This is using llvm::COFF::header which does not handle endianess. This code is
incorrect on big endian machines. The structs from llvm/Object/COFF.h should be
used instead. They are designed for this purpose.
+ && header_->SizeOfOptionalHeader != OptionalHeaderSize )
+ { error_ = "Bad optional header size" ; return ; }
+ if ( header_->PointerToSymbolTable >= data_size_ )
+ { error_ = "Symbol table offset too big" ; return ; }
+
+ // Make sure that there's enough room in the file for the section
headers, and read them.
+ if ( header_->SizeOfOptionalHeader + HeaderSize +
(header_->NumberOfSections * SectionSize) > data_size_ )
+ { error_ = "File too small for section headers" ; return ; }
+
+ // Advance past the headers
+ std::size_t section_offset = HeaderSize + header_->SizeOfOptionalHeader;
+ for ( uint32_t i = 0; i < header_->NumberOfSections; ++i ) {
+ const section *s = offset_cast<const section *> ( section_offset +
( i * SectionSize ));
+ if ( s->PointerToRawData + s->SizeOfRawData > data_size_ )
+ { error_ = "Section header RawData too large" ; return ; }
+ if ( s->PointerToRelocations > data_size_ )
+ { error_ = "Section header PointerToRelocations too large" ; return ; }
+ if ( s->PointerToLineNumbers > data_size_ )
+ { error_ = "Section header PointerToLineNumbers too large" ; return ; }
+ section_headers_.push_back ( *s );
+ }
+
+ // Make sure the string table is a valid size, and read it.
+ std::size_t stringTableOffset = header_->PointerToSymbolTable
+ + header_->NumberOfSymbols * SymbolSize;
+ if ( stringTableOffset > data_size_ )
+ { error_ = "Non-existant string table" ; return ; }
+
+ string_table_size_ = data_size_ - stringTableOffset;
+ string_table_ = offset_cast<const char *> ( stringTableOffset );
+ valid_ = true;
+ }
+
+
+ std::ostream& obj2yaml::write_section ( std::ostream &out, const
section §,
+ const unsigned char *sectionData, std::size_t sectionDataLength,
+ const relocation *relocations, std::size_t numRelocations ) {
+ const my_pair<SectionCharacteristics, const char *> *ptr;
+
+ out << " - !Section" << std::endl;
+ out << " Name: ";
+ yaml_name ( out, sect.Name, NameSize ) << std::endl;
+
+ out << " Characteristics: [";
+ for ( ptr = SectionCharacteristicsPairs1;
+ ptr != SectionCharacteristicsPairs1 + ArrSize
(SectionCharacteristicsPairs1); ++ptr )
+ if ( ptr->first & sect.Characteristics )
+ out << ptr->second << ", ";
+
+ out << name_lookup ( SectionCharacteristicNamesAlignment,
+ sect.Characteristics & 0x00F00000, "#
Unrecognized_IMAGE_SCN_ALIGN" ) << ", ";
+
+ for ( ptr = SectionCharacteristicsPairs2;
+ ptr != SectionCharacteristicsPairs2 + ArrSize
(SectionCharacteristicsPairs2); ++ptr )
+ if ( ptr->first & sect.Characteristics )
+ out << ptr->second << ", ";
+
+ out << "] # 0x" << sect.Characteristics << std::endl;
+ yaml_hex_stream ( out, " SectionData: ", sectionData, sectionDataLength );
+ out << std::endl;
+ if ( numRelocations > 0 ) {
+ out << " Relocations: " << std::endl;
+ for ( std::size_t i = 0; i < numRelocations; ++i ) {
+ const relocation *p = pointer_offset_cast<const relocation *> (
relocations, i * RelocationSize );
+ out << " - !Relocation" << std::endl;
+ out << " VirtualAddress: " << p->VirtualAddress <<
std::endl; // hex!
+ out << " SymbolTableIndex: " << p->SymbolTableIndex << std::endl;
+ out << " Type: " << std::endl;
+ out << std::endl;
+ }
+ }
+ return out;
+ }
+
+ std::ostream& obj2yaml::write_symbols ( std::ostream &out, const
symbol *symbols, std::size_t numSymbols ) {
+ out << "symbols:" << std::endl;
+ for ( std::size_t i = 0; i < numSymbols; ++i ) {
+ const symbol *p = pointer_offset_cast<const symbol *> ( symbols, i
* SymbolSize );
+ out << " - !Symbol" << std::endl;
+ out << " Name: ";
+ if (0 != p->Name[0]) // the name is inline
+ yaml_name ( out, p->Name, NameSize ) << std::endl;
+ else { // the name is in the string table
+ uint32_t offset = *reinterpret_cast<const uint32_t *> (p->Name + 4);
+ out << string_table_ + offset << std::endl; // D'oh!
+ }
+ out << " Value: " << p->Value << std::endl;
+ out << " SectionNumber: " << (int) p->SectionNumber << std::endl;
+ // out << " Type: " << (int) p->Type << std::endl;
+ std::size_t simpleType = p->Type & 0x0F; // LSB of type
+ std::size_t complexType = ( p->Type >> 8 ) & 0x0F; // MSB of type
+
+ out << " SimpleType: "
+ << name_lookup ( SymbolBaseTypeNames, simpleType, "#
Unknown_SymbolBaseType" )
+ << " # (" << simpleType << ")" << std::endl;
+ out << " ComplexType: "
+ << name_lookup ( SymbolComplexTypeNames, complexType, "#
Unknown_SymbolComplexType" )
+ << " # (" << simpleType << ")" << std::endl;
+ out << " StorageClass: "
+ << name_lookup ( SymbolStorageClassNames, p->StorageClass, "#
Unknown_StorageClass" )
+ << " # (" << (int) p->StorageClass << ")" << std::endl;
+
+ // out << " StorageClass: " << (int) p->StorageClass << std::endl;
+ if ( p->NumberOfAuxSymbols > 0 ) {
+ out << " NumberOfAuxSymbols: " << (int) p->NumberOfAuxSymbols
<< std::endl;
+ yaml_hex_stream ( out, " AuxillaryData: ",
+ reinterpret_cast<const unsigned char*> (p) + SymbolSize, SymbolSize );
+ ++i; // skip the next one
+ }
+
+ out << std::endl;
+ }
+
+ return out;
+ }
+
+
+ std::ostream & obj2yaml::write_yaml ( std::ostream &out ) {
+ out << std::hex << std::uppercase;
+ // Dump out the header
+ out << "header: !Header" << std::endl;
+ out << " Machine: ";
+ out << name_lookup ( MachineTypeNames, header_->Machine, "#
Unknown_MachineTypes" );
+ out << " # (0x" << header_->Machine << ")" << std::endl << std::endl;
+
+ // Dump out the sections
+ out << "sections:" << std::endl;
+ for ( std::vector<section>::const_iterator iter = section_headers_.begin ();
+ iter != section_headers_.end (); ++iter ) {
+ // std::cout << "## -> There are " << iter->SizeOfRawData << "
bytes of raw data and " << iter->NumberOfRelocations << " relocations"
<< std::endl;
+
+ const unsigned char *sectionData = offset_cast<const unsigned char
*> ( iter->PointerToRawData );
+ const relocation *relocationData = offset_cast<const relocation *>
( iter->PointerToRelocations );
+ this->write_section ( out, *iter, sectionData,
+ iter->SizeOfRawData, relocationData, iter->NumberOfRelocations );
+ }
+
+ // Read and dump out the symbols
+ const symbol *symbolData = offset_cast<const symbol *> (
header_->PointerToSymbolTable );
+ this->write_symbols ( out, symbolData, header_->NumberOfSymbols );
+
+ return out;
+ }
+
+ } // end of namespace coff
+
+
+using namespace llvm;
+
+enum ObjectFileType { coff } ;
+
+cl::opt<ObjectFileType> InputFormat(
+ cl::desc("Choose input format"),
+ cl::values (
+ clEnumVal ( coff, "process COFF object files" ),
+ clEnumValEnd ));
+
+cl::opt<std::string> InputFilename(cl::Positional, cl::desc("<input
file>"), cl::init("-"));
+
+int main ( int argc, char * argv[] ) {
+ cl::ParseCommandLineOptions(argc, argv);
+ sys::PrintStackTraceOnErrorSignal();
+ PrettyStackTraceProgram X(argc, argv);
+ llvm_shutdown_obj Y; // Call llvm_shutdown() on exit.
+
+// Process the input file
+ OwningPtr<MemoryBuffer> buf;
+ error_code ec = MemoryBuffer::getFile ( InputFilename, buf, -1, false );
This should be getFileOrSTDIN.
+
+// TODO: If this is an archive, then burst it and dump each entry
+ if ( ec != error_code::success ())
This can just be if (ec). Or better yet, if (error_code ec =
MemoryBuffer::getFileOrSTDIN(...))
+ std::cerr << "Can't open file '" << InputFilename << "' for
reading" << std::endl;
This should print out the error given by ec.
+ else {
+ coff2yaml::obj2yaml coff ( buf->getBufferStart (), buf->getBufferSize ());
+ if ( coff.is_valid ())
+ coff.write_yaml ( std::cout );
+ else {
+ std::cerr << "## Error reading/parsing '" << InputFilename << "'"
<< std::endl;
+ std::cerr << " Message: '" << coff.error_message () << "'" << std::endl;
+ }
+ }
+
+ return 0;
+ }
- Michael Spencer
More information about the llvm-commits
mailing list