|
1 | 1 | module ObjFileBase
|
2 | 2 |
|
3 |
| -# package code goes here |
| 3 | +export ObjectHandle, SectionRef, SymbolRef |
| 4 | + |
| 5 | +import Base: read, seek, readbytes, position |
| 6 | + |
| 7 | +########## ObjFileBase.jl - Basic shared functionality for all object files #### |
| 8 | +# |
| 9 | +# This package provides basic functionality that is shared among object files. |
| 10 | +# It was written with ELF/MachO/COFF in mind, but should be easily adaptable |
| 11 | +# to other object files as well. |
| 12 | +# |
| 13 | +# The family of Object file implementations have a somewhat different focus than |
| 14 | +# a lot of other ones. While certainly usable to write a linker or compiler, |
| 15 | +# they are more intended for interactive exploration and verification and some |
| 16 | +# of the design choices reflect this. Nevertheless, this does not mean that |
| 17 | +# performance should be unnecessarily compromised. |
| 18 | +# |
| 19 | +# # # Basic Concepts |
| 20 | +# |
| 21 | +# # ObjectHandle |
| 22 | +# |
| 23 | +# Provides an abstraction over a specific instance of the object file. |
| 24 | +# Currently many implementations put the IO object to be read from in this |
| 25 | +# handle, which has proven convenient for interactive usage. |
| 26 | +# |
| 27 | +# # SectionIterator, SymbolIterator, etc. |
| 28 | +# |
| 29 | +# Provides support for iterating over Symbols, Sections, Relocations, etc. |
| 30 | +# These should have a reference to the original ObjectHandle and read the |
| 31 | +# desired information on demand. Rather than returning the read datastructure |
| 32 | +# directly, it should return in in an appropriate *Ref object. |
| 33 | +# |
| 34 | +# # SetionRef, SymbolRef |
| 35 | +# |
| 36 | +# Convenience objects (mostly for interactive usage) that contain a reference |
| 37 | +# to the original object handle as well as any information that may be needed |
| 38 | +# to get further information about the Referenced object that is not |
| 39 | +# explicitly encoded in the data structure itself. Examples may include: |
| 40 | +# |
| 41 | +# - Offset in the file (especially for variable length records |
| 42 | +# where only the header is part of the datastructure) |
| 43 | +# - Symbol/Section index |
| 44 | +# - Etc. |
| 45 | +# |
| 46 | +################################################################################ |
| 47 | + |
| 48 | +# # # Tools |
| 49 | + |
| 50 | +macro mustimplement(sig) |
| 51 | + fname = sig.args[1] |
| 52 | + arg1 = sig.args[2] |
| 53 | + if isa(arg1,Expr) |
| 54 | + arg1 = arg1.args[1] |
| 55 | + end |
| 56 | + :($(esc(sig)) = error(typeof($(esc(arg1))), |
| 57 | + " must implement ", $(Expr(:quote,fname)))) |
| 58 | +end |
| 59 | + |
| 60 | +################################# Interfaces ################################### |
| 61 | + |
| 62 | +# # # ObjectHandle |
| 63 | + |
| 64 | +abstract ObjectHandle |
| 65 | + |
| 66 | +# External facing interface |
| 67 | +readmeta{T<:ObjectHandle}(io::IO, ::Type{T}) = |
| 68 | + error("$T must register a readmeta method") |
| 69 | + |
| 70 | +@mustimplement readheader(oh::ObjectHandle) |
| 71 | + |
| 72 | +# Querying general properties |
| 73 | +@mustimplement endianness(oh::ObjectHandle) |
| 74 | + |
| 75 | +# ObjectHandle IO interface |
| 76 | +@mustimplement seek(oh::ObjectHandle, args...) |
| 77 | +@mustimplement position(oh::ObjectHandle) |
| 78 | + |
| 79 | +## |
| 80 | +# These are parameterized on the type of Object Handle. An imaginary Foo |
| 81 | +# fileformat might declare: |
| 82 | +# |
| 83 | +# module Foo |
| 84 | +# immutable FooHandle; ... end |
| 85 | +# immutable Section <: ObjFileBase.Section{FooHandle} |
| 86 | +# ...; end |
| 87 | +# end |
| 88 | +## |
| 89 | + |
| 90 | +abstract SectionRef{T<:ObjectHandle} |
| 91 | +abstract Section{T<:ObjectHandle} |
| 92 | + |
| 93 | +# The size of the actual data contained in the section. This should exclude any |
| 94 | +# padding mandated by the file format e.g. due to alignment rules |
| 95 | +@mustimplement sectionsize(section::Section) |
| 96 | + |
| 97 | +# The offset of the section in the file |
| 98 | +@mustimplement sectionoffset(section::Section) |
| 99 | + |
| 100 | +# Retrieving the actual section datastructure |
| 101 | +@mustimplement deref(section::SectionRef) |
| 102 | + |
| 103 | +# Retrieving the object handle |
| 104 | +@mustimplement handle(section::SectionRef) |
| 105 | + |
| 106 | +abstract SymbolRef{T<:ObjectHandle} |
| 107 | +abstract SymtabEntry{T<:ObjectHandle} |
| 108 | + |
| 109 | +################################# Utilities #################################### |
| 110 | + |
| 111 | +typealias SectionOrRef{T} Union(Section{T},SectionRef{T}) |
| 112 | + |
| 113 | +sectionsize(sect::SectionRef) = sectionsize(deref(sect)) |
| 114 | +sectionoffset(sect::SectionRef) = sectionoffset(deref(sect)) |
| 115 | + |
| 116 | +seek{T<:ObjectHandle}(oh::T, section::Section{T}) = |
| 117 | + seek(oh,sectionoffset(section)) |
| 118 | + |
| 119 | +seek(section::SectionRef) = seek(handle(section), deref(section)) |
| 120 | + |
| 121 | +function readbytes{T<:ObjectHandle}(oh::T,sec::Section{T}) |
| 122 | + seek(oh, sec) |
| 123 | + readbytes(oh, sectionsize(sec)) |
| 124 | +end |
| 125 | +readbytes(sec::SectionRef) = readbytes(handle(sec),deref(sec)) |
| 126 | + |
| 127 | +# # # DWARF support |
| 128 | +# |
| 129 | +# Whether or not this is the right place to put this is up for debate, but |
| 130 | +# this way, DWARF does not need to be concerned with the specific notion of |
| 131 | +# being embedded in an object file. |
| 132 | +# |
| 133 | +# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # |
| 134 | + |
| 135 | +using DWARF |
| 136 | + |
| 137 | +@mustimplement debugsections(oh::ObjectHandle) |
| 138 | + |
| 139 | +function read{T<:ObjectHandle}(oh::T,sec::Section{T},::Type{DWARF.ARTable}) |
| 140 | + seek(oh, sec) |
| 141 | + ret = DWARF.ARTable(Array(DWARF.ARTableSet,0)) |
| 142 | + while position(oh) < sectionoffset(sec) + sectionsize(sec) |
| 143 | + push!(ret.sets, read(oh, DWARF.ARTableSet, endianness(oh))) |
| 144 | + end |
| 145 | + ret |
| 146 | +end |
| 147 | + |
| 148 | +function read{T<:ObjectHandle}(oh::T,sec::Section{T},::Type{DWARF.PUBTable}) |
| 149 | + seek(oh, sec) |
| 150 | + ret = DWARF.PUBTable(Array(DWARF.PUBTableSet,0)) |
| 151 | + while position(oh) < sectionoffset(sec) + sectionsize(sec) |
| 152 | + push!(ret.sets,read(oh,DWARF.PUBTableSet, endianness(oh))) |
| 153 | + end |
| 154 | + ret |
| 155 | +end |
| 156 | + |
| 157 | +function read{T<:ObjectHandle}(oh::T, sec::Section{T}, |
| 158 | + ::Type{DWARF.AbbrevTableSet}) |
| 159 | + seek(oh, sec) |
| 160 | + read(oh, AbbrevTableSet, endianness(oh)) |
| 161 | +end |
| 162 | + |
| 163 | +function read{T<:ObjectHandle}(oh::T,sec::Section{T}, |
| 164 | + s::DWARF.PUBTableSet,::Type{DWARF.DWARFCUHeader}) |
| 165 | + |
| 166 | + seek(oh,sectionoffsect(debug_info)+s.header.debug_info_offset) |
| 167 | + read(oh,DWARF.DWARFCUHeader, endianness(oh)) |
| 168 | +end |
| 169 | + |
| 170 | +function read{T<:ObjectHandle}(oh::T, sec::Section{T}, s::DWARF.DWARFCUHeader, |
| 171 | + ::Type{DWARF.AbbrevTableSet}) |
| 172 | + |
| 173 | + seek(oh,sectionoffsect(debug_info)+s.debug_abbrev_offset) |
| 174 | + read(oh,DWARF.AbbrevTableSet, endianness(oh)) |
| 175 | +end |
| 176 | + |
| 177 | +function read{T<:ObjectHandle}(oh::T, |
| 178 | + debug_info::Section{T}, debug_abbrev::Section{T}, |
| 179 | + s::DWARF.PUBTableSet, e::DWARF.PUBTableEntry, |
| 180 | + header::DWARF.DWARFCUHeader, ::Type{DWARF.DIETree}) |
| 181 | + |
| 182 | + ats = read(oh,debug_abbrev,header,DWARF.AbbrevTableSet) |
| 183 | + seek(oh,sectionoffset(offset)+s.header.debug_info_offset+e.offset) |
| 184 | + ret = DWARF.DIETree(Array(DWARF.DIETreeNode,0)) |
| 185 | + read(oh,header,ats,ret,DWARF.DIETreeNode,:LittleEndian) |
| 186 | + ret |
| 187 | +end |
4 | 188 |
|
5 | 189 | end # module
|
0 commit comments