Commit 3d124b1a authored by Hiroshi Ioka's avatar Hiroshi Ioka Committed by Ian Lance Taylor

debug/macho: support LC_RPATH

Updates #21487

Change-Id: Ia549a87a8a305cc80da11ea9bd904402f1a14689
Reviewed-on: https://go-review.googlesource.com/56321Reviewed-by: 's avatarIan Lance Taylor <iant@golang.org>
Run-TryBot: Ian Lance Taylor <iant@golang.org>
TryBot-Result: Gobot Gobot <gobot@golang.org>
parent 2763672e
......@@ -143,6 +143,12 @@ type Dysymtab struct {
IndirectSyms []uint32 // indices into Symtab.Syms
}
// A Rpath represents a Mach-O rpath command.
type Rpath struct {
LoadBytes
Path string
}
// A Symbol is a Mach-O 32-bit or 64-bit symbol table entry.
type Symbol struct {
Name string
......@@ -258,6 +264,19 @@ func NewFile(r io.ReaderAt) (*File, error) {
default:
f.Loads[i] = LoadBytes(cmddat)
case LoadCmdRpath:
var hdr RpathCmd
b := bytes.NewReader(cmddat)
if err := binary.Read(b, bo, &hdr); err != nil {
return nil, err
}
l := new(Rpath)
if hdr.Path >= uint32(len(cmddat)) {
return nil, &FormatError{offset, "invalid path in rpath command", hdr.Path}
}
l.Path = cstring(cmddat[hdr.Path:])
f.Loads[i] = l
case LoadCmdDylib:
var hdr DylibCmd
b := bytes.NewReader(cmddat)
......
......@@ -96,6 +96,52 @@ var fileTests = []fileTest{
{"__debug_str", "__DWARF", 0x10000215c, 0x60, 0x115c, 0x0, 0x0, 0x0, 0x0},
},
},
{
"testdata/clang-386-darwin-exec-with-rpath",
FileHeader{0xfeedface, Cpu386, 0x3, 0x2, 0x10, 0x42c, 0x1200085},
[]interface{}{
nil, // LC_SEGMENT
nil, // LC_SEGMENT
nil, // LC_SEGMENT
nil, // LC_SEGMENT
nil, // LC_DYLD_INFO_ONLY
nil, // LC_SYMTAB
nil, // LC_DYSYMTAB
nil, // LC_LOAD_DYLINKER
nil, // LC_UUID
nil, // LC_VERSION_MIN_MACOSX
nil, // LC_SOURCE_VERSION
nil, // LC_MAIN
nil, // LC_LOAD_DYLIB
&Rpath{nil, "/my/rpath"},
nil, // LC_FUNCTION_STARTS
nil, // LC_DATA_IN_CODE
},
nil,
},
{
"testdata/clang-amd64-darwin-exec-with-rpath",
FileHeader{0xfeedfacf, CpuAmd64, 0x80000003, 0x2, 0x10, 0x4c8, 0x200085},
[]interface{}{
nil, // LC_SEGMENT
nil, // LC_SEGMENT
nil, // LC_SEGMENT
nil, // LC_SEGMENT
nil, // LC_DYLD_INFO_ONLY
nil, // LC_SYMTAB
nil, // LC_DYSYMTAB
nil, // LC_LOAD_DYLINKER
nil, // LC_UUID
nil, // LC_VERSION_MIN_MACOSX
nil, // LC_SOURCE_VERSION
nil, // LC_MAIN
nil, // LC_LOAD_DYLIB
&Rpath{nil, "/my/rpath"},
nil, // LC_FUNCTION_STARTS
nil, // LC_DATA_IN_CODE
},
nil,
},
}
func TestOpen(t *testing.T) {
......@@ -133,6 +179,12 @@ func TestOpen(t *testing.T) {
if !reflect.DeepEqual(have, want) {
t.Errorf("open %s, segment %d:\n\thave %#v\n\twant %#v\n", tt.file, i, have, want)
}
case *Rpath:
have := l
have.LoadBytes = nil
if !reflect.DeepEqual(have, want) {
t.Errorf("open %s, segment %d:\n\thave %#v\n\twant %#v\n", tt.file, i, have, want)
}
default:
t.Errorf("open %s, section %d: unknown load command\n\thave %#v\n\twant %#v\n", tt.file, i, l, want)
}
......@@ -143,22 +195,23 @@ func TestOpen(t *testing.T) {
t.Errorf("open %s: len(Loads) = %d, want %d", tt.file, fn, tn)
}
for i, sh := range f.Sections {
if i >= len(tt.sections) {
break
if tt.sections != nil {
for i, sh := range f.Sections {
if i >= len(tt.sections) {
break
}
have := &sh.SectionHeader
want := tt.sections[i]
if !reflect.DeepEqual(have, want) {
t.Errorf("open %s, section %d:\n\thave %#v\n\twant %#v\n", tt.file, i, have, want)
}
}
have := &sh.SectionHeader
want := tt.sections[i]
if !reflect.DeepEqual(have, want) {
t.Errorf("open %s, section %d:\n\thave %#v\n\twant %#v\n", tt.file, i, have, want)
tn = len(tt.sections)
fn = len(f.Sections)
if tn != fn {
t.Errorf("open %s: len(Sections) = %d, want %d", tt.file, fn, tn)
}
}
tn = len(tt.sections)
fn = len(f.Sections)
if tn != fn {
t.Errorf("open %s: len(Sections) = %d, want %d", tt.file, fn, tn)
}
}
}
......
......@@ -87,6 +87,7 @@ const (
LoadCmdDylib LoadCmd = 0xc // load dylib command
LoadCmdDylinker LoadCmd = 0xf // id dylinker command (not load dylinker command)
LoadCmdSegment64 LoadCmd = 0x19
LoadCmdRpath LoadCmd = 0x8000001c
)
var cmdStrings = []intName{
......@@ -95,6 +96,7 @@ var cmdStrings = []intName{
{uint32(LoadCmdUnixThread), "LoadCmdUnixThread"},
{uint32(LoadCmdDylib), "LoadCmdDylib"},
{uint32(LoadCmdSegment64), "LoadCmdSegment64"},
{uint32(LoadCmdRpath), "LoadCmdRpath"},
}
func (i LoadCmd) String() string { return stringName(uint32(i), cmdStrings, false) }
......@@ -175,6 +177,13 @@ type (
CompatVersion uint32
}
// A RpathCmd is a Mach-O rpath command.
RpathCmd struct {
Cmd LoadCmd
Len uint32
Path uint32
}
// A Thread is a Mach-O thread state command.
Thread struct {
Cmd LoadCmd
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment