mirror of
https://github.com/blacktop/ipsw.git
synced 2026-05-08 12:22:26 +00:00
8e6f2c554b
Refactor string concatenation to use strings.Builder for improved performance in multiple files
1061 lines
22 KiB
Go
1061 lines
22 KiB
Go
package ctf
|
|
|
|
import (
|
|
"bytes"
|
|
"encoding/json"
|
|
"fmt"
|
|
"strconv"
|
|
"strings"
|
|
"text/tabwriter"
|
|
)
|
|
|
|
type Type interface {
|
|
ID() int
|
|
Name() string
|
|
Info() Info
|
|
ParentID() int
|
|
Type() string
|
|
String() string
|
|
Dump() string
|
|
}
|
|
|
|
type Integer struct {
|
|
id int
|
|
name string
|
|
info Info
|
|
encoding intEncoding
|
|
}
|
|
|
|
func (i *Integer) ID() int {
|
|
return i.id
|
|
}
|
|
func (i *Integer) Name() string {
|
|
return i.name
|
|
}
|
|
func (i *Integer) Info() Info {
|
|
return i.info
|
|
}
|
|
func (i *Integer) Encoding() string {
|
|
return i.encoding.Encoding().String()
|
|
}
|
|
func (i *Integer) Offset() uint32 {
|
|
return i.encoding.Offset()
|
|
}
|
|
func (i *Integer) Bits() uint32 {
|
|
return i.encoding.Bits()
|
|
}
|
|
func (i *Integer) ParentID() int {
|
|
return 0
|
|
}
|
|
func (i *Integer) Type() string {
|
|
return i.name
|
|
}
|
|
func (i *Integer) String() string {
|
|
return i.name
|
|
}
|
|
func (i *Integer) Dump() string {
|
|
return fmt.Sprintf("%s %s %s encoding=%s offset=%d bits=%d\n",
|
|
isRootIDFmtStr(i.info.IsRoot(), i.id),
|
|
i.info.Kind(),
|
|
i.name,
|
|
i.encoding.Encoding(),
|
|
i.encoding.Offset(),
|
|
i.encoding.Bits(),
|
|
)
|
|
}
|
|
func (i *Integer) MarshalJSON() ([]byte, error) {
|
|
return json.Marshal(&struct {
|
|
ID int `json:"id,omitempty"`
|
|
Name string `json:"name,omitempty"`
|
|
Info Info `json:"info,omitempty"`
|
|
Encoding intEncoding `json:"encoding,omitempty"`
|
|
}{
|
|
ID: i.id,
|
|
Name: i.name,
|
|
Info: i.info,
|
|
Encoding: i.encoding,
|
|
})
|
|
}
|
|
|
|
type Float struct {
|
|
id int
|
|
name string
|
|
info Info
|
|
encoding floatEncoding
|
|
}
|
|
|
|
func (f *Float) ID() int {
|
|
return f.id
|
|
}
|
|
func (f *Float) Name() string {
|
|
return f.name
|
|
}
|
|
func (f *Float) Info() Info {
|
|
return f.info
|
|
}
|
|
func (f *Float) Encoding() string {
|
|
return f.encoding.Encoding().String()
|
|
}
|
|
func (f *Float) Offset() uint32 {
|
|
return f.encoding.Offset()
|
|
}
|
|
func (f *Float) Bits() uint32 {
|
|
return f.encoding.Bits()
|
|
}
|
|
func (f *Float) ParentID() int {
|
|
return 0
|
|
}
|
|
func (f *Float) Type() string {
|
|
return f.name
|
|
}
|
|
func (f *Float) String() string {
|
|
return f.name
|
|
}
|
|
func (f *Float) Dump() string {
|
|
return fmt.Sprintf("%s %s %s encoding=%s offset=%d bits=%d",
|
|
isRootIDFmtStr(f.info.IsRoot(), f.id),
|
|
f.info.Kind(),
|
|
f.name,
|
|
f.encoding.Encoding(),
|
|
f.encoding.Offset(),
|
|
f.encoding.Bits(),
|
|
)
|
|
}
|
|
func (f *Float) MarshalJSON() ([]byte, error) {
|
|
return json.Marshal(&struct {
|
|
ID int `json:"id,omitempty"`
|
|
Name string `json:"name,omitempty"`
|
|
Info Info `json:"info,omitempty"`
|
|
Encoding floatEncoding `json:"encoding,omitempty"`
|
|
}{
|
|
ID: f.id,
|
|
Name: f.name,
|
|
Info: f.info,
|
|
Encoding: f.encoding,
|
|
})
|
|
}
|
|
|
|
type Array struct {
|
|
id int
|
|
name string
|
|
info Info
|
|
array
|
|
lookupFn func(int) Type
|
|
}
|
|
|
|
func (a *Array) ID() int {
|
|
return a.id
|
|
}
|
|
func (a *Array) Name() string {
|
|
if a.name == "(anon)" {
|
|
return ""
|
|
}
|
|
return " " + a.name
|
|
}
|
|
func (a *Array) Info() Info {
|
|
return a.info
|
|
}
|
|
func (a *Array) Index() string {
|
|
if t := a.lookupFn(int(a.array.Index)); t != nil {
|
|
return t.Type()
|
|
}
|
|
return "<type not found>"
|
|
}
|
|
func (a *Array) Contents() string {
|
|
if t := a.lookupFn(int(a.array.Contents)); t != nil {
|
|
return t.Type()
|
|
}
|
|
return "<type not found>"
|
|
}
|
|
func (a *Array) ParentID() int {
|
|
return 0
|
|
}
|
|
func (a *Array) Type() string {
|
|
return strings.TrimSuffix(a.String(), ";")
|
|
}
|
|
func (a *Array) String() string {
|
|
return fmt.Sprintf(
|
|
"%s%s[%d];",
|
|
a.Contents(),
|
|
a.Name(),
|
|
a.NumElements,
|
|
)
|
|
}
|
|
func (a *Array) Dump() string {
|
|
return fmt.Sprintf("%s %s %s content: %d index: %d nelems: %d",
|
|
isRootIDFmtStr(a.info.IsRoot(), a.id),
|
|
a.info.Kind(),
|
|
a.name,
|
|
a.array.Contents,
|
|
a.array.Index,
|
|
a.array.NumElements,
|
|
)
|
|
}
|
|
func (a *Array) MarshalJSON() ([]byte, error) {
|
|
return json.Marshal(&struct {
|
|
ID int `json:"id,omitempty"`
|
|
Name string `json:"name,omitempty"`
|
|
Info Info `json:"info,omitempty"`
|
|
ContentsID uint `json:"contents_id,omitempty"` /* reference to type of array contents */
|
|
Contents string `json:"contents,omitempty"` /* reference to type of array contents */
|
|
IndexID uint `json:"index_id,omitempty"` /* reference to type of array index */
|
|
IndexType string `json:"index_type,omitempty"` /* reference to type of array index */
|
|
NumElements uint32 `json:"num_elements,omitempty"` /* number of elements */
|
|
}{
|
|
ID: a.id,
|
|
Name: a.name,
|
|
Info: a.info,
|
|
ContentsID: uint(a.array.Contents),
|
|
Contents: a.Contents(),
|
|
IndexID: uint(a.array.Index),
|
|
IndexType: a.Index(),
|
|
NumElements: a.array.NumElements,
|
|
})
|
|
}
|
|
|
|
type Function struct {
|
|
id int
|
|
name string
|
|
info Info
|
|
ret uint
|
|
args []uint32
|
|
lookupFn func(int) Type
|
|
}
|
|
|
|
type funcArg struct {
|
|
ID int `json:"id,omitempty"`
|
|
Type string `json:"type,omitempty"`
|
|
}
|
|
|
|
func (f *Function) ID() int {
|
|
return f.id
|
|
}
|
|
func (f *Function) Name() string {
|
|
return f.name
|
|
}
|
|
func (f *Function) Info() Info {
|
|
return f.info
|
|
}
|
|
func (f *Function) Return() string {
|
|
if t := f.lookupFn(int(f.ret)); t != nil {
|
|
return t.Type()
|
|
}
|
|
return "<return type not found>"
|
|
}
|
|
func (f *Function) Args() string {
|
|
var argStrs []string
|
|
for idx, arg := range f.args {
|
|
if t := f.lookupFn(int(arg)); t != nil {
|
|
argStrs = append(argStrs, t.Type())
|
|
} else {
|
|
return fmt.Sprintf("<arg%d type not found>", idx)
|
|
}
|
|
}
|
|
return strings.Join(argStrs, ", ")
|
|
}
|
|
func (f *Function) ParentID() int {
|
|
return 0
|
|
}
|
|
func (f *Function) Type() string {
|
|
return strings.TrimSuffix(f.String(), ";")
|
|
}
|
|
func (f *Function) String() string {
|
|
return fmt.Sprintf(
|
|
"%s %s(%s);",
|
|
f.Return(),
|
|
f.name,
|
|
f.Args(),
|
|
)
|
|
}
|
|
func (f *Function) Dump() string {
|
|
var fdump string
|
|
fdump = fmt.Sprintf("%s %s %s returns: %d args: (",
|
|
isRootIDFmtStr(f.info.IsRoot(), f.id),
|
|
f.info.Kind(),
|
|
f.name,
|
|
f.ret,
|
|
)
|
|
var sargs []string
|
|
for _, a := range f.args {
|
|
sargs = append(sargs, strconv.Itoa(int(a)))
|
|
}
|
|
fdump += fmt.Sprintf("%s)", strings.Join(sargs, ","))
|
|
return fdump
|
|
}
|
|
func (f *Function) MarshalJSON() ([]byte, error) {
|
|
var args []funcArg
|
|
for idx, arg := range f.args {
|
|
if t := f.lookupFn(int(arg)); t != nil {
|
|
args = append(args, funcArg{
|
|
ID: int(arg),
|
|
Type: t.Type(),
|
|
})
|
|
} else {
|
|
args = append(args, funcArg{
|
|
ID: int(arg),
|
|
Type: fmt.Sprintf("<arg%d type ref %d not found>", idx, arg),
|
|
})
|
|
}
|
|
}
|
|
return json.Marshal(&struct {
|
|
ID int `json:"id,omitempty"`
|
|
Name string `json:"name,omitempty"`
|
|
Info Info `json:"info,omitempty"`
|
|
ReturnID uint `json:"return_id,omitempty"`
|
|
Return string `json:"return,omitempty"`
|
|
Arguments []funcArg `json:"arguments,omitempty"`
|
|
}{
|
|
ID: f.id,
|
|
Name: f.name,
|
|
Info: f.info,
|
|
ReturnID: uint(f.ret),
|
|
Return: f.Return(),
|
|
Arguments: args,
|
|
})
|
|
}
|
|
|
|
type Member struct {
|
|
parent int
|
|
name string
|
|
offset uint64
|
|
reference uint
|
|
lookupFn func(int) Type
|
|
}
|
|
|
|
func (m Member) ParentID() int {
|
|
return m.parent
|
|
}
|
|
func (m Member) Name() string {
|
|
return m.name
|
|
}
|
|
func (m Member) Type() string {
|
|
if t := m.lookupFn(int(m.reference)); t != nil {
|
|
return t.Type()
|
|
}
|
|
return "<member type not found>"
|
|
}
|
|
func (m Member) Offset() uint64 {
|
|
return m.offset
|
|
}
|
|
func (m Member) MarshalJSON() ([]byte, error) {
|
|
return json.Marshal(&struct {
|
|
ID int `json:"id,omitempty"`
|
|
Name string `json:"name,omitempty"`
|
|
Type string `json:"type,omitempty"`
|
|
Offset uint64 `json:"offset"`
|
|
}{
|
|
ID: int(m.reference),
|
|
Name: m.name,
|
|
Type: m.Type(),
|
|
Offset: m.offset,
|
|
})
|
|
}
|
|
|
|
type Struct struct {
|
|
id int
|
|
name string
|
|
info Info
|
|
size uint64
|
|
Fields []Member
|
|
lookupFn func(int) Type
|
|
}
|
|
|
|
func (s *Struct) ID() int {
|
|
return s.id
|
|
}
|
|
func (s *Struct) Name() string {
|
|
if s.name == "(anon)" {
|
|
return ""
|
|
}
|
|
return s.name
|
|
}
|
|
func (s *Struct) Info() Info {
|
|
return s.info
|
|
}
|
|
func (s *Struct) ParentID() int {
|
|
return 0
|
|
}
|
|
func (s *Struct) Size() uint64 {
|
|
return s.size
|
|
}
|
|
func (s *Struct) Type() string {
|
|
if s.name == "(anon)" {
|
|
return strings.TrimSuffix(s.String(), ";")
|
|
}
|
|
return "struct " + s.Name()
|
|
}
|
|
func (s *Struct) String() string {
|
|
buf := bytes.NewBufferString("")
|
|
w := tabwriter.NewWriter(buf, 0, 0, 1, ' ', 0)
|
|
fmt.Fprintf(w,
|
|
"struct %s {\t\t// (%d bytes)\n",
|
|
s.Name(),
|
|
s.size,
|
|
)
|
|
for _, f := range s.Fields {
|
|
t := s.lookupFn(int(f.reference))
|
|
if t != nil && t.Info().Kind() == ARRAY {
|
|
fmt.Fprintf(w, " %s\t%s[%d];\t// off=%#x\n",
|
|
t.(*Array).Contents(),
|
|
f.name,
|
|
t.(*Array).NumElements,
|
|
f.offset,
|
|
)
|
|
} else {
|
|
fmt.Fprintf(w, " %s\t%s;\t// off=%#x\n",
|
|
f.Type(),
|
|
f.name,
|
|
f.offset,
|
|
)
|
|
}
|
|
}
|
|
fmt.Fprintf(w, "};")
|
|
w.Flush()
|
|
return buf.String()
|
|
}
|
|
func (s *Struct) Dump() string {
|
|
buf := bytes.NewBufferString("")
|
|
w := tabwriter.NewWriter(buf, 0, 0, 1, ' ', 0)
|
|
fmt.Fprintf(w, "%s %s %s (%d bytes)\n",
|
|
isRootIDFmtStr(s.info.IsRoot(), s.id),
|
|
s.info.Kind(),
|
|
s.name,
|
|
s.size,
|
|
)
|
|
for _, f := range s.Fields {
|
|
fmt.Fprintf(w, " %s\ttype=%d\toff=%#x\n",
|
|
f.Name(),
|
|
f.reference,
|
|
f.offset,
|
|
)
|
|
}
|
|
w.Flush()
|
|
return buf.String()
|
|
}
|
|
func (s *Struct) MarshalJSON() ([]byte, error) {
|
|
return json.Marshal(&struct {
|
|
ID int `json:"id,omitempty"`
|
|
Name string `json:"name,omitempty"`
|
|
Info Info `json:"info,omitempty"`
|
|
Size uint64 `json:"size,omitempty"`
|
|
Fields []Member `json:"fields,omitempty"`
|
|
}{
|
|
ID: s.id,
|
|
Name: s.name,
|
|
Info: s.info,
|
|
Size: s.size,
|
|
Fields: s.Fields,
|
|
})
|
|
}
|
|
|
|
type Union struct {
|
|
id int
|
|
name string
|
|
info Info
|
|
size uint64
|
|
Fields []Member
|
|
lookupFn func(int) Type
|
|
}
|
|
|
|
func (s *Union) ID() int {
|
|
return s.id
|
|
}
|
|
func (s *Union) Name() string {
|
|
if s.name == "(anon)" {
|
|
return ""
|
|
}
|
|
return s.name
|
|
}
|
|
func (s *Union) Info() Info {
|
|
return s.info
|
|
}
|
|
func (s *Union) ParentID() int {
|
|
return 0
|
|
}
|
|
func (s *Union) Size() uint64 {
|
|
return s.size
|
|
}
|
|
func (s *Union) Type() string {
|
|
return "union " + s.name
|
|
}
|
|
func (s *Union) String() string {
|
|
buf := bytes.NewBufferString("")
|
|
w := tabwriter.NewWriter(buf, 0, 0, 1, ' ', 0)
|
|
fmt.Fprintf(w,
|
|
"union %s {\t\t// (%d bytes)\n",
|
|
s.Name(),
|
|
s.size,
|
|
)
|
|
for _, f := range s.Fields {
|
|
t := s.lookupFn(int(f.reference))
|
|
if t != nil && t.Info().Kind() == ARRAY {
|
|
fmt.Fprintf(w, " %s\t%s[%d];\n",
|
|
t.(*Array).Contents(),
|
|
f.name,
|
|
t.(*Array).NumElements,
|
|
)
|
|
} else {
|
|
fmt.Fprintf(w, " %s\t%s;\n",
|
|
f.Type(),
|
|
f.name,
|
|
)
|
|
}
|
|
}
|
|
fmt.Fprintf(w, "};")
|
|
w.Flush()
|
|
return buf.String()
|
|
}
|
|
func (s *Union) Dump() string {
|
|
var sdump string
|
|
sdump = fmt.Sprintf("%s %s %s (%d bytes)\n",
|
|
isRootIDFmtStr(s.info.IsRoot(), s.id),
|
|
s.info.Kind(),
|
|
s.name,
|
|
s.size,
|
|
)
|
|
for _, f := range s.Fields {
|
|
sdump += fmt.Sprintf("\t%s type=%d off=%#x\n",
|
|
f.Name(),
|
|
f.reference,
|
|
f.offset,
|
|
)
|
|
}
|
|
return sdump
|
|
}
|
|
func (s *Union) MarshalJSON() ([]byte, error) {
|
|
return json.Marshal(&struct {
|
|
ID int `json:"id,omitempty"`
|
|
Name string `json:"name,omitempty"`
|
|
Info Info `json:"info,omitempty"`
|
|
Size uint64 `json:"size,omitempty"`
|
|
Fields []Member `json:"fields,omitempty"`
|
|
}{
|
|
ID: s.id,
|
|
Name: s.name,
|
|
Info: s.info,
|
|
Size: s.size,
|
|
Fields: s.Fields,
|
|
})
|
|
}
|
|
|
|
type enumField struct {
|
|
Name string `json:"name,omitempty"`
|
|
Value int32 `json:"value,omitempty"`
|
|
}
|
|
|
|
type Enum struct {
|
|
id int
|
|
name string
|
|
info Info
|
|
Fields []enumField
|
|
}
|
|
|
|
func (e *Enum) ID() int {
|
|
return e.id
|
|
}
|
|
func (e *Enum) Name() string {
|
|
return e.name
|
|
}
|
|
func (e *Enum) Info() Info {
|
|
return e.info
|
|
}
|
|
func (e *Enum) ParentID() int {
|
|
return 0
|
|
}
|
|
func (e *Enum) Type() string { return "enum " + e.name }
|
|
func (e *Enum) String() string {
|
|
var eout strings.Builder
|
|
eout.WriteString(fmt.Sprintf("enum %s {\n", e.name))
|
|
for _, f := range e.Fields {
|
|
eout.WriteString(fmt.Sprintf("\t%s = %d\n",
|
|
f.Name,
|
|
f.Value,
|
|
))
|
|
}
|
|
eout.WriteString("};")
|
|
return eout.String()
|
|
}
|
|
func (e *Enum) Dump() string {
|
|
var edump string
|
|
edump = fmt.Sprintf("%s %s %s\n",
|
|
isRootIDFmtStr(e.info.IsRoot(), e.id),
|
|
e.info.Kind(),
|
|
e.name,
|
|
)
|
|
for _, f := range e.Fields {
|
|
edump += fmt.Sprintf("\t%s = %d\n",
|
|
f.Name,
|
|
f.Value,
|
|
)
|
|
}
|
|
return edump
|
|
}
|
|
func (e *Enum) MarshalJSON() ([]byte, error) {
|
|
return json.Marshal(&struct {
|
|
ID int `json:"id,omitempty"`
|
|
Name string `json:"name,omitempty"`
|
|
Info Info `json:"info,omitempty"`
|
|
Fields []enumField `json:"fields,omitempty"`
|
|
}{
|
|
ID: e.id,
|
|
Name: e.name,
|
|
Info: e.info,
|
|
Fields: e.Fields,
|
|
})
|
|
}
|
|
|
|
type Forward struct {
|
|
id int
|
|
name string
|
|
info Info
|
|
}
|
|
|
|
func (f *Forward) ID() int {
|
|
return f.id
|
|
}
|
|
func (f *Forward) Name() string {
|
|
return f.name
|
|
}
|
|
func (f *Forward) Info() Info {
|
|
return f.info
|
|
}
|
|
func (f *Forward) ParentID() int {
|
|
return 0
|
|
}
|
|
func (f *Forward) Type() string {
|
|
return f.name
|
|
}
|
|
func (f *Forward) String() string {
|
|
return f.name
|
|
}
|
|
func (f *Forward) Dump() string {
|
|
return fmt.Sprintf("%s %s %s",
|
|
isRootIDFmtStr(f.info.IsRoot(), f.id),
|
|
f.info.Kind(),
|
|
f.name,
|
|
)
|
|
}
|
|
func (f *Forward) MarshalJSON() ([]byte, error) {
|
|
return json.Marshal(&struct {
|
|
ID int `json:"id,omitempty"`
|
|
Name string `json:"name,omitempty"`
|
|
Info Info `json:"info,omitempty"`
|
|
}{
|
|
ID: f.id,
|
|
Name: f.name,
|
|
Info: f.info,
|
|
})
|
|
}
|
|
|
|
type Pointer struct {
|
|
id int
|
|
name string
|
|
info Info
|
|
reference uint
|
|
lookupFn func(int) Type
|
|
}
|
|
|
|
func (p *Pointer) ID() int {
|
|
return p.id
|
|
}
|
|
func (p *Pointer) Name() string {
|
|
return p.name
|
|
}
|
|
func (p *Pointer) Info() Info {
|
|
return p.info
|
|
}
|
|
func (p *Pointer) Reference() string {
|
|
if t := p.lookupFn(int(p.reference)); t != nil {
|
|
return t.Type()
|
|
}
|
|
return "<reference type not found>"
|
|
}
|
|
func (p *Pointer) ParentID() int {
|
|
return int(p.reference)
|
|
}
|
|
func (p *Pointer) Type() string {
|
|
return strings.TrimSuffix(p.String(), ";")
|
|
}
|
|
func (p *Pointer) String() string {
|
|
return fmt.Sprintf("%s *;", p.Reference())
|
|
}
|
|
func (p *Pointer) Dump() string {
|
|
return fmt.Sprintf("%s %s %s refers to %d",
|
|
isRootIDFmtStr(p.info.IsRoot(), p.id),
|
|
p.info.Kind(),
|
|
p.name,
|
|
p.reference,
|
|
)
|
|
}
|
|
func (p *Pointer) MarshalJSON() ([]byte, error) {
|
|
return json.Marshal(&struct {
|
|
ID int `json:"id,omitempty"`
|
|
Name string `json:"name,omitempty"`
|
|
Info Info `json:"info,omitempty"`
|
|
ReferenceID uint `json:"reference_id,omitempty"`
|
|
Reference string `json:"reference,omitempty"`
|
|
}{
|
|
ID: p.id,
|
|
Name: p.name,
|
|
Info: p.info,
|
|
ReferenceID: uint(p.reference),
|
|
Reference: p.Reference(),
|
|
})
|
|
}
|
|
|
|
type Typedef struct {
|
|
id int
|
|
name string
|
|
info Info
|
|
reference uint
|
|
lookupFn func(int) Type
|
|
}
|
|
|
|
func (p *Typedef) ID() int {
|
|
return p.id
|
|
}
|
|
func (p *Typedef) Name() string {
|
|
return p.name
|
|
}
|
|
func (p *Typedef) Info() Info {
|
|
return p.info
|
|
}
|
|
func (p *Typedef) Reference() string {
|
|
if t := p.lookupFn(int(p.reference)); t != nil {
|
|
return t.Type()
|
|
}
|
|
return "<reference type not found>"
|
|
}
|
|
func (p *Typedef) ParentID() int {
|
|
return int(p.reference)
|
|
}
|
|
func (p *Typedef) Type() string {
|
|
return p.Name()
|
|
}
|
|
func (p *Typedef) String() string {
|
|
return fmt.Sprintf("typedef %s %s", p.name, p.Reference())
|
|
}
|
|
func (p *Typedef) Dump() string {
|
|
return fmt.Sprintf("%s %s %s refers to %d",
|
|
isRootIDFmtStr(p.info.IsRoot(), p.id),
|
|
p.info.Kind(),
|
|
p.name,
|
|
p.reference,
|
|
)
|
|
}
|
|
func (p *Typedef) MarshalJSON() ([]byte, error) {
|
|
return json.Marshal(&struct {
|
|
ID int `json:"id,omitempty"`
|
|
Name string `json:"name,omitempty"`
|
|
Info Info `json:"info,omitempty"`
|
|
ReferenceID uint `json:"reference_id,omitempty"`
|
|
Reference string `json:"reference,omitempty"`
|
|
}{
|
|
ID: p.id,
|
|
Name: p.name,
|
|
Info: p.info,
|
|
ReferenceID: uint(p.reference),
|
|
Reference: p.Reference(),
|
|
})
|
|
}
|
|
|
|
type Volatile struct {
|
|
id int
|
|
name string
|
|
info Info
|
|
reference uint
|
|
lookupFn func(int) Type
|
|
}
|
|
|
|
func (p *Volatile) ID() int {
|
|
return p.id
|
|
}
|
|
func (p *Volatile) Name() string {
|
|
return p.name
|
|
}
|
|
func (p *Volatile) Info() Info {
|
|
return p.info
|
|
}
|
|
func (p *Volatile) Reference() string {
|
|
if t := p.lookupFn(int(p.reference)); t != nil {
|
|
return t.Type()
|
|
}
|
|
return "<reference type not found>"
|
|
}
|
|
func (p *Volatile) ParentID() int {
|
|
return int(p.reference)
|
|
}
|
|
func (p *Volatile) Type() string {
|
|
return fmt.Sprintf("volatile %s", p.Reference())
|
|
}
|
|
func (p *Volatile) String() string {
|
|
return fmt.Sprintf("volatile %s", p.Reference())
|
|
}
|
|
func (p *Volatile) Dump() string {
|
|
return fmt.Sprintf("%s %s %s refers to %d",
|
|
isRootIDFmtStr(p.info.IsRoot(), p.id),
|
|
p.info.Kind(),
|
|
p.name,
|
|
p.reference,
|
|
)
|
|
}
|
|
func (p *Volatile) MarshalJSON() ([]byte, error) {
|
|
return json.Marshal(&struct {
|
|
ID int `json:"id,omitempty"`
|
|
Name string `json:"name,omitempty"`
|
|
Info Info `json:"info,omitempty"`
|
|
ReferenceID uint `json:"reference_id,omitempty"`
|
|
Reference string `json:"reference,omitempty"`
|
|
}{
|
|
ID: p.id,
|
|
Name: p.name,
|
|
Info: p.info,
|
|
ReferenceID: uint(p.reference),
|
|
Reference: p.Reference(),
|
|
})
|
|
}
|
|
|
|
type Const struct {
|
|
id int
|
|
name string
|
|
info Info
|
|
reference uint
|
|
lookupFn func(int) Type
|
|
}
|
|
|
|
func (p *Const) ID() int {
|
|
return p.id
|
|
}
|
|
func (p *Const) Name() string {
|
|
return p.name
|
|
}
|
|
func (p *Const) Info() Info {
|
|
return p.info
|
|
}
|
|
func (p *Const) Reference() string {
|
|
if t := p.lookupFn(int(p.reference)); t != nil {
|
|
return t.Type()
|
|
}
|
|
return "<reference type not found>"
|
|
}
|
|
func (p *Const) ParentID() int {
|
|
return int(p.reference)
|
|
}
|
|
func (p *Const) Type() string {
|
|
return fmt.Sprintf("const %s", p.Reference())
|
|
}
|
|
func (p *Const) String() string {
|
|
return fmt.Sprintf("const %s", p.Reference())
|
|
}
|
|
func (p *Const) Dump() string {
|
|
return fmt.Sprintf("%s %s %s refers to %d",
|
|
isRootIDFmtStr(p.info.IsRoot(), p.id),
|
|
p.info.Kind(),
|
|
p.name,
|
|
p.reference,
|
|
)
|
|
}
|
|
func (p *Const) MarshalJSON() ([]byte, error) {
|
|
return json.Marshal(&struct {
|
|
ID int `json:"id,omitempty"`
|
|
Name string `json:"name,omitempty"`
|
|
Info Info `json:"info,omitempty"`
|
|
ReferenceID uint `json:"reference_id,omitempty"`
|
|
Reference string `json:"reference,omitempty"`
|
|
}{
|
|
ID: p.id,
|
|
Name: p.name,
|
|
Info: p.info,
|
|
ReferenceID: uint(p.reference),
|
|
Reference: p.Reference(),
|
|
})
|
|
}
|
|
|
|
type Restrict struct {
|
|
id int
|
|
name string
|
|
info Info
|
|
reference uint
|
|
lookupFn func(int) Type
|
|
}
|
|
|
|
func (p *Restrict) ID() int {
|
|
return p.id
|
|
}
|
|
func (p *Restrict) Name() string {
|
|
return p.name
|
|
}
|
|
func (p *Restrict) Info() Info {
|
|
return p.info
|
|
}
|
|
func (p *Restrict) Reference() string {
|
|
if t := p.lookupFn(int(p.reference)); t != nil {
|
|
return t.Type()
|
|
}
|
|
return "<reference type not found>"
|
|
}
|
|
func (p *Restrict) ParentID() int {
|
|
return int(p.reference)
|
|
}
|
|
func (p *Restrict) Type() string {
|
|
return fmt.Sprintf("restrict %s", p.Reference())
|
|
}
|
|
func (p *Restrict) String() string {
|
|
return fmt.Sprintf("restrict %s", p.Reference())
|
|
}
|
|
func (p *Restrict) Dump() string {
|
|
return fmt.Sprintf("%s %s %s refers to %d",
|
|
isRootIDFmtStr(p.info.IsRoot(), p.id),
|
|
p.info.Kind(),
|
|
p.name,
|
|
p.reference,
|
|
)
|
|
}
|
|
func (p *Restrict) MarshalJSON() ([]byte, error) {
|
|
return json.Marshal(&struct {
|
|
ID int `json:"id,omitempty"`
|
|
Name string `json:"name,omitempty"`
|
|
Info Info `json:"info,omitempty"`
|
|
ReferenceID uint `json:"reference_id,omitempty"`
|
|
Reference string `json:"reference,omitempty"`
|
|
}{
|
|
ID: p.id,
|
|
Name: p.name,
|
|
Info: p.info,
|
|
ReferenceID: uint(p.reference),
|
|
Reference: p.Reference(),
|
|
})
|
|
}
|
|
|
|
type PtrAuth struct {
|
|
id int
|
|
name string
|
|
info Info
|
|
data ptrAuthData
|
|
reference uint
|
|
lookupFn func(int) Type
|
|
}
|
|
|
|
func (p *PtrAuth) ID() int {
|
|
return p.id
|
|
}
|
|
func (p *PtrAuth) Name() string {
|
|
return p.name
|
|
}
|
|
func (p *PtrAuth) Info() Info {
|
|
return p.info
|
|
}
|
|
func (p *PtrAuth) Reference() string {
|
|
if t := p.lookupFn(int(p.reference)); t != nil {
|
|
return t.Type()
|
|
}
|
|
return "<reference type not found>"
|
|
}
|
|
func (p *PtrAuth) ParentID() int {
|
|
return int(p.reference)
|
|
}
|
|
func (p *PtrAuth) Type() string { return p.String() }
|
|
func (p *PtrAuth) String() string {
|
|
return fmt.Sprintf(
|
|
"%s __ptrauth(%s, %t, %04x)",
|
|
p.Reference(),
|
|
p.data.Key(),
|
|
p.data.Discriminated(),
|
|
p.data.Discriminator(),
|
|
)
|
|
}
|
|
func (p *PtrAuth) Dump() string {
|
|
return fmt.Sprintf("%s %s %s refers to %d (key=%s, addr_div=%t, div=%04x)",
|
|
isRootIDFmtStr(p.info.IsRoot(), p.id),
|
|
p.info.Kind(),
|
|
p.name,
|
|
p.reference,
|
|
p.data.Key(),
|
|
p.data.Discriminated(),
|
|
p.data.Discriminator(),
|
|
)
|
|
}
|
|
func (p *PtrAuth) MarshalJSON() ([]byte, error) {
|
|
return json.Marshal(&struct {
|
|
ID int `json:"id,omitempty"`
|
|
Name string `json:"name,omitempty"`
|
|
Info Info `json:"info,omitempty"`
|
|
Data ptrAuthData `json:"data,omitempty"`
|
|
ReferenceID uint `json:"reference_id,omitempty"`
|
|
Reference string `json:"reference,omitempty"`
|
|
}{
|
|
ID: p.id,
|
|
Name: p.name,
|
|
Info: p.info,
|
|
Data: p.data,
|
|
ReferenceID: uint(p.reference),
|
|
Reference: p.Reference(),
|
|
})
|
|
}
|
|
|
|
type global struct {
|
|
Address uint64 `json:"address,omitempty"`
|
|
Name string `json:"name,omitempty"`
|
|
Reference int `json:"reference,omitempty"`
|
|
Type Type `json:"type,omitempty"`
|
|
}
|
|
|
|
func (g global) String() string {
|
|
if g.Type != nil {
|
|
return fmt.Sprintf("%#x: %s %s", g.Address, g.Type.Type(), g.Name)
|
|
}
|
|
if g.Reference == 0 {
|
|
return fmt.Sprintf("%#x: <unknown> %s", g.Address, g.Name)
|
|
}
|
|
return fmt.Sprintf("%#x: %d %s", g.Address, g.Reference, g.Name)
|
|
}
|
|
|
|
type function struct {
|
|
Address uint64 `json:"address,omitempty"`
|
|
Name string `json:"name,omitempty"`
|
|
Return Type `json:"return,omitempty"`
|
|
Arguments []Type `json:"arguments,omitempty"`
|
|
}
|
|
|
|
func (f function) String() string {
|
|
var args []string
|
|
for _, arg := range f.Arguments {
|
|
args = append(args, arg.Type())
|
|
}
|
|
return fmt.Sprintf("%#x: %s %s(%s);", f.Address, f.Return.Type(), f.Name, strings.Join(args, ", "))
|
|
}
|
|
|
|
func isRootIDFmtStr(isroot bool, id int) string {
|
|
if isroot {
|
|
return fmt.Sprintf("<%d>", id)
|
|
}
|
|
return fmt.Sprintf("[%d]", id)
|
|
}
|
|
|
|
func (h header) String() string {
|
|
return fmt.Sprintf(
|
|
"Magic = %#x\n"+
|
|
"Version = %d\n"+
|
|
"Flags = %#x\n"+
|
|
"Parent Label = %s\n"+
|
|
"Parent Name = %s\n"+
|
|
"Label Offset = %d\n"+
|
|
"Obj Offset = %d\n"+
|
|
"Func Offset = %#x\n"+
|
|
"Type Offset = %#x\n"+
|
|
"Str Offset = %#x\n"+
|
|
"Str Len = %#x\n",
|
|
h.Preamble.Magic,
|
|
h.Preamble.Version,
|
|
h.Preamble.Flags,
|
|
h.ParentLabel,
|
|
h.ParentName,
|
|
h.LabelOffset,
|
|
h.ObjOffset,
|
|
h.FuncOffset,
|
|
h.TypeOffset,
|
|
h.StrOffset,
|
|
h.StrLen,
|
|
)
|
|
}
|