github.com/Rookout/GoSDK@v0.1.48/pkg/services/instrumentation/binary_info/binary_info_darwin.go (about) 1 // The MIT License (MIT) 2 3 // Copyright (c) 2014 Derek Parker 4 5 // Permission is hereby granted, free of charge, to any person obtaining a copy of 6 // this software and associated documentation files (the "Software"), to deal in 7 // the Software without restriction, including without limitation the rights to 8 // use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of 9 // the Software, and to permit persons to whom the Software is furnished to do so, 10 // subject to the following conditions: 11 12 // The above copyright notice and this permission notice shall be included in all 13 // copies or substantial portions of the Software. 14 15 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS 17 // FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR 18 // COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER 19 // IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 20 // CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 21 22 //go:build darwin 23 // +build darwin 24 25 package binary_info 26 27 import ( 28 "debug/macho" 29 "errors" 30 "sync" 31 32 "github.com/Rookout/GoSDK/pkg/logger" 33 "github.com/Rookout/GoSDK/pkg/services/instrumentation/dwarf/frame" 34 "github.com/Rookout/GoSDK/pkg/services/instrumentation/dwarf/godwarf" 35 "github.com/Rookout/GoSDK/pkg/utils" 36 ) 37 38 type archID = macho.Cpu 39 type File = macho.File 40 41 var supportedArchs = map[macho.Cpu]interface{}{ 42 macho.CpuAmd64: nil, 43 macho.CpuArm64: nil, 44 } 45 46 const crosscall2SPOffset = 0x58 47 48 49 50 func loadBinaryInfo(bi *BinaryInfo, image *Image, path string, entryPoint uint64) error { 51 exe, err := macho.Open(path) 52 if err != nil { 53 return err 54 } 55 if entryPoint != 0 { 56 57 58 59 60 image.StaticBase = entryPoint - 0x100000000 61 } 62 image.closer = exe 63 if !isSupportedArch(exe.Cpu) { 64 return errors.New("unsupported darwin arch") 65 } 66 image.Dwarf, err = exe.DWARF() 67 if err != nil { 68 return err 69 } 70 debugInfoBytes, err := GetDebugSection(exe, "info") 71 if err != nil { 72 return err 73 } 74 75 debugLineBytes, err := GetDebugSection(exe, "line") 76 if err != nil { 77 return err 78 } 79 bi.debugLocBytes, _ = GetDebugSection(exe, "loc") 80 bi.debugLoclistBytes, _ = GetDebugSection(exe, "loclists") 81 debugAddrBytes, _ := GetDebugSection(exe, "addr") 82 image.debugAddr = godwarf.ParseAddr(debugAddrBytes) 83 debugLineStrBytes, _ := GetDebugSection(exe, "line_str") 84 image.debugLineStr = debugLineStrBytes 85 86 wg := &sync.WaitGroup{} 87 wg.Add(2) 88 utils.CreateGoroutine(func() { 89 defer wg.Done() 90 err = bi.parseDebugFrame(image, exe, debugInfoBytes) 91 if err != nil { 92 logger.Logger().WithError(err).Error("Failed to parse debug frame") 93 } 94 }) 95 utils.CreateGoroutine(func() { 96 defer wg.Done() 97 err = bi.loadDebugInfoMaps(image, debugInfoBytes, debugLineBytes) 98 if err != nil { 99 logger.Logger().WithError(err).Error("Failed to load debug info maps") 100 } 101 }) 102 wg.Wait() 103 bi.macOSDebugFrameBugWorkaround() 104 return nil 105 } 106 107 func getSectionName(section string) string { 108 return "__debug_" + section 109 } 110 111 func getCompressedSectionName(section string) string { 112 return "__zdebug_" + section 113 } 114 115 func getEhFrameSection(f *macho.File) *macho.Section { 116 return f.Section("__eh_frame") 117 } 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 func (bi *BinaryInfo) macOSDebugFrameBugWorkaround() { 140 if len(bi.Images) > 1 { 141 142 143 144 return 145 } 146 147 148 var fn *Function 149 for i := range bi.Functions { 150 if bi.Functions[i].cu.IsGo && bi.Functions[i].Entry > 0 { 151 fn = &bi.Functions[i] 152 break 153 } 154 } 155 if fn == nil { 156 157 return 158 } 159 160 if fde, _ := bi.FrameEntries.FDEForPC(fn.Entry); fde != nil { 161 162 163 return 164 } 165 166 167 var fde *frame.FrameDescriptionEntry 168 for i := range bi.FrameEntries { 169 if bi.FrameEntries[i].CIE.CIE_id == ^uint32(0) { 170 fde = bi.FrameEntries[i] 171 break 172 } 173 } 174 175 if fde == nil { 176 177 return 178 } 179 180 fnsize := fn.End - fn.Entry 181 182 if fde.End()-fde.Begin() != fnsize || fde.Begin() > fn.Entry { 183 184 return 185 } 186 187 delta := fn.Entry - fde.Begin() 188 189 190 191 for i := range bi.FrameEntries { 192 if bi.FrameEntries[i].CIE.CIE_id == ^uint32(0) { 193 bi.FrameEntries[i].Translate(delta) 194 } 195 } 196 }