From 3d124b1a817146ab7800982622b0de5b828f3392 Mon Sep 17 00:00:00 2001 From: Hiroshi Ioka Date: Thu, 17 Aug 2017 09:11:36 +0900 Subject: [PATCH] debug/macho: support LC_RPATH Updates #21487 Change-Id: Ia549a87a8a305cc80da11ea9bd904402f1a14689 Reviewed-on: https://go-review.googlesource.com/56321 Reviewed-by: Ian Lance Taylor Run-TryBot: Ian Lance Taylor TryBot-Result: Gobot Gobot --- src/debug/macho/file.go | 19 +++++ src/debug/macho/file_test.go | 79 +++++++++++++++--- src/debug/macho/macho.go | 9 ++ .../testdata/clang-386-darwin-exec-with-rpath | Bin 0 -> 8416 bytes .../clang-amd64-darwin-exec-with-rpath | Bin 0 -> 8432 bytes 5 files changed, 94 insertions(+), 13 deletions(-) create mode 100644 src/debug/macho/testdata/clang-386-darwin-exec-with-rpath create mode 100644 src/debug/macho/testdata/clang-amd64-darwin-exec-with-rpath diff --git a/src/debug/macho/file.go b/src/debug/macho/file.go index 306e9ae1da..cbf24787be 100644 --- a/src/debug/macho/file.go +++ b/src/debug/macho/file.go @@ -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) diff --git a/src/debug/macho/file_test.go b/src/debug/macho/file_test.go index 01a8e70121..30705b1bc7 100644 --- a/src/debug/macho/file_test.go +++ b/src/debug/macho/file_test.go @@ -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) - } - } } diff --git a/src/debug/macho/macho.go b/src/debug/macho/macho.go index 045adb090a..907be31341 100644 --- a/src/debug/macho/macho.go +++ b/src/debug/macho/macho.go @@ -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 diff --git a/src/debug/macho/testdata/clang-386-darwin-exec-with-rpath b/src/debug/macho/testdata/clang-386-darwin-exec-with-rpath new file mode 100644 index 0000000000000000000000000000000000000000..a8720feb923693232bce4fa9642988c86a28c372 GIT binary patch literal 8416 zcmeHM&r1|h9Dl284Q8nwN-%O14GVJ%f;rQo=QFb}r?L72;(gigy!ZY2zV9<{Vc&k&zkU9( zQwY%rZUDD|2ckmU5@sZV`4Cvj@sYFf>+vg>At<8bUx;yc@Q`vcK0O(5VvLHz$aS0Q zOfM;2Yr*Brr*QmCmk>u`nrRgRC2mnvEGj|DVmX`4+p_4El2C?oEF;Gb=$Da$bt*EN z{2a6)2ZCkVvI~~u$-nPo1v&OXzk(dZ>=)H@P?mDG=sKC)&AKsM$0~B{fo&Bzf)var zWhpnG$)#i_H<)dNWfrXuHHxeU8plaFDY}t(1)_% zI)98e=!n>0&BRaPDy5zHR}RDU-=h)Aq0S@IGnan`FOFTh5FZ^==jj*>h!ds|8yFa) z*2Prx2(d^P+UeGYu>+%`e$&?vVH|*xd!RiHnP=+}My|UHJPr;LeH91w!TEhNbVln& zzVid%7I3UobYgZU8B3Mz6y#1YYv_D;@9X-tleZu5KmX)``Q~XablihzY4-StlBomr zW3P);ax#(Ki!83!XA(QlK^KyChWy>+AkZ{w8KLlnC zDbwHA;krz`G-(7h0vZ90fJQ(gpb^jrXaqC@J_1vf_e-BTHYrTsT|AB9W&As(O0;)# zH^$?yEAcOtS4%HCZalBn`V13ykSHFtK3-j_{Ov71e5}=KxQ^QS0dqd@*r{gkuETo- zDLC?XKJNki-B0E{m&7^mcP)r)^P;KUqKCLkYSIX31T+E~0gZr0KqH_L&6X&9mRy#6Y0Wp+gUP^kPWg#3orZLXs77!9;$qMRYZV; z2AwKj;P>;%tYw!h2SKg*)>Xbfm4KMM*JaoE=F6^=E8JB9t@)m-dYIfb}2hwt&9T-R-=l;g3PSjdC*Yg*S}eM9StJy*{yWx_qKcI-0548DPp$D93SsaA;?wZ}jcs|Ov{Ltkgj3bx!TOU*Tym98M zQKyu0vv8e;vfnw==k=_@Gy|Fe&46a$UomhivHCHw^2JE3T^dE7 zuj4=1^9!+k0A^%sHU52dGqLi@n0;9rSVq;v+VOiZvFX}C3U;0Ew&L@rTCIjpO1n5{ zE*2d-)8&0r;9c00u;sfn-?h)fQXi@JZkG8y(~Xvf*BYSt)5NQIg7}D6(htpmW{uc&%`;95irFV>%ecolbOyhnSm)BE{SQn1bJ0?rG zfOZ#vAQ6fC_%@l(N^8lQuecWOx>F24nNQ^kVt_v&+Qo+xjD-XRR`*2wn?e3xIOJjf nUj;G$VZhdZJ@8&JjQzBz6k?2J6F0=W#~{5i1moQ`BeeSkgV?^% literal 0 HcmV?d00001 -- 2.50.0