You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 

327 lines
6.5 KiB

  1. // Copyright 2018 Google Inc. All Rights Reserved.
  2. //
  3. // Licensed under the Apache License, Version 2.0 (the "License");
  4. // you may not use this file except in compliance with the License.
  5. // You may obtain a copy of the License at
  6. //
  7. // http://www.apache.org/licenses/LICENSE-2.0
  8. //
  9. // Unless required by applicable law or agreed to in writing, software
  10. // distributed under the License is distributed on an "AS IS" BASIS,
  11. // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  12. // See the License for the specific language governing permissions and
  13. // limitations under the License.
  14. // Mach-O header data structures
  15. // http://developer.apple.com/mac/library/documentation/DeveloperTools/Conceptual/MachORuntime/Reference/reference.html
  16. package macho // import "cloud.google.com/go/cmd/go-cloud-debug-agent/internal/debug/macho"
  17. import "strconv"
  18. // A FileHeader represents a Mach-O file header.
  19. type FileHeader struct {
  20. Magic uint32
  21. Cpu Cpu
  22. SubCpu uint32
  23. Type Type
  24. Ncmd uint32
  25. Cmdsz uint32
  26. Flags uint32
  27. }
  28. const (
  29. fileHeaderSize32 = 7 * 4
  30. fileHeaderSize64 = 8 * 4
  31. )
  32. const (
  33. Magic32 uint32 = 0xfeedface
  34. Magic64 uint32 = 0xfeedfacf
  35. MagicFat uint32 = 0xcafebabe
  36. )
  37. // A Type is the Mach-O file type, e.g. an object file, executable, or dynamic library.
  38. type Type uint32
  39. const (
  40. TypeObj Type = 1
  41. TypeExec Type = 2
  42. TypeDylib Type = 6
  43. TypeBundle Type = 8
  44. )
  45. // A Cpu is a Mach-O cpu type.
  46. type Cpu uint32
  47. const cpuArch64 = 0x01000000
  48. const (
  49. Cpu386 Cpu = 7
  50. CpuAmd64 Cpu = Cpu386 | cpuArch64
  51. CpuArm Cpu = 12
  52. CpuPpc Cpu = 18
  53. CpuPpc64 Cpu = CpuPpc | cpuArch64
  54. )
  55. var cpuStrings = []intName{
  56. {uint32(Cpu386), "Cpu386"},
  57. {uint32(CpuAmd64), "CpuAmd64"},
  58. {uint32(CpuArm), "CpuArm"},
  59. {uint32(CpuPpc), "CpuPpc"},
  60. {uint32(CpuPpc64), "CpuPpc64"},
  61. }
  62. func (i Cpu) String() string { return stringName(uint32(i), cpuStrings, false) }
  63. func (i Cpu) GoString() string { return stringName(uint32(i), cpuStrings, true) }
  64. // A LoadCmd is a Mach-O load command.
  65. type LoadCmd uint32
  66. const (
  67. LoadCmdSegment LoadCmd = 1
  68. LoadCmdSymtab LoadCmd = 2
  69. LoadCmdThread LoadCmd = 4
  70. LoadCmdUnixThread LoadCmd = 5 // thread+stack
  71. LoadCmdDysymtab LoadCmd = 11
  72. LoadCmdDylib LoadCmd = 12
  73. LoadCmdDylinker LoadCmd = 15
  74. LoadCmdSegment64 LoadCmd = 25
  75. )
  76. var cmdStrings = []intName{
  77. {uint32(LoadCmdSegment), "LoadCmdSegment"},
  78. {uint32(LoadCmdThread), "LoadCmdThread"},
  79. {uint32(LoadCmdUnixThread), "LoadCmdUnixThread"},
  80. {uint32(LoadCmdDylib), "LoadCmdDylib"},
  81. {uint32(LoadCmdSegment64), "LoadCmdSegment64"},
  82. }
  83. func (i LoadCmd) String() string { return stringName(uint32(i), cmdStrings, false) }
  84. func (i LoadCmd) GoString() string { return stringName(uint32(i), cmdStrings, true) }
  85. // A Segment64 is a 64-bit Mach-O segment load command.
  86. type Segment64 struct {
  87. Cmd LoadCmd
  88. Len uint32
  89. Name [16]byte
  90. Addr uint64
  91. Memsz uint64
  92. Offset uint64
  93. Filesz uint64
  94. Maxprot uint32
  95. Prot uint32
  96. Nsect uint32
  97. Flag uint32
  98. }
  99. // A Segment32 is a 32-bit Mach-O segment load command.
  100. type Segment32 struct {
  101. Cmd LoadCmd
  102. Len uint32
  103. Name [16]byte
  104. Addr uint32
  105. Memsz uint32
  106. Offset uint32
  107. Filesz uint32
  108. Maxprot uint32
  109. Prot uint32
  110. Nsect uint32
  111. Flag uint32
  112. }
  113. // A DylibCmd is a Mach-O load dynamic library command.
  114. type DylibCmd struct {
  115. Cmd LoadCmd
  116. Len uint32
  117. Name uint32
  118. Time uint32
  119. CurrentVersion uint32
  120. CompatVersion uint32
  121. }
  122. // A Section32 is a 32-bit Mach-O section header.
  123. type Section32 struct {
  124. Name [16]byte
  125. Seg [16]byte
  126. Addr uint32
  127. Size uint32
  128. Offset uint32
  129. Align uint32
  130. Reloff uint32
  131. Nreloc uint32
  132. Flags uint32
  133. Reserve1 uint32
  134. Reserve2 uint32
  135. }
  136. // A Section32 is a 64-bit Mach-O section header.
  137. type Section64 struct {
  138. Name [16]byte
  139. Seg [16]byte
  140. Addr uint64
  141. Size uint64
  142. Offset uint32
  143. Align uint32
  144. Reloff uint32
  145. Nreloc uint32
  146. Flags uint32
  147. Reserve1 uint32
  148. Reserve2 uint32
  149. Reserve3 uint32
  150. }
  151. // A SymtabCmd is a Mach-O symbol table command.
  152. type SymtabCmd struct {
  153. Cmd LoadCmd
  154. Len uint32
  155. Symoff uint32
  156. Nsyms uint32
  157. Stroff uint32
  158. Strsize uint32
  159. }
  160. // A DysymtabCmd is a Mach-O dynamic symbol table command.
  161. type DysymtabCmd struct {
  162. Cmd LoadCmd
  163. Len uint32
  164. Ilocalsym uint32
  165. Nlocalsym uint32
  166. Iextdefsym uint32
  167. Nextdefsym uint32
  168. Iundefsym uint32
  169. Nundefsym uint32
  170. Tocoffset uint32
  171. Ntoc uint32
  172. Modtaboff uint32
  173. Nmodtab uint32
  174. Extrefsymoff uint32
  175. Nextrefsyms uint32
  176. Indirectsymoff uint32
  177. Nindirectsyms uint32
  178. Extreloff uint32
  179. Nextrel uint32
  180. Locreloff uint32
  181. Nlocrel uint32
  182. }
  183. // An Nlist32 is a Mach-O 32-bit symbol table entry.
  184. type Nlist32 struct {
  185. Name uint32
  186. Type uint8
  187. Sect uint8
  188. Desc uint16
  189. Value uint32
  190. }
  191. // An Nlist64 is a Mach-O 64-bit symbol table entry.
  192. type Nlist64 struct {
  193. Name uint32
  194. Type uint8
  195. Sect uint8
  196. Desc uint16
  197. Value uint64
  198. }
  199. // A Symbol is a Mach-O 32-bit or 64-bit symbol table entry.
  200. type Symbol struct {
  201. Name string
  202. Type uint8
  203. Sect uint8
  204. Desc uint16
  205. Value uint64
  206. }
  207. // A Thread is a Mach-O thread state command.
  208. type Thread struct {
  209. Cmd LoadCmd
  210. Len uint32
  211. Type uint32
  212. Data []uint32
  213. }
  214. // Regs386 is the Mach-O 386 register structure.
  215. type Regs386 struct {
  216. AX uint32
  217. BX uint32
  218. CX uint32
  219. DX uint32
  220. DI uint32
  221. SI uint32
  222. BP uint32
  223. SP uint32
  224. SS uint32
  225. FLAGS uint32
  226. IP uint32
  227. CS uint32
  228. DS uint32
  229. ES uint32
  230. FS uint32
  231. GS uint32
  232. }
  233. // RegsAMD64 is the Mach-O AMD64 register structure.
  234. type RegsAMD64 struct {
  235. AX uint64
  236. BX uint64
  237. CX uint64
  238. DX uint64
  239. DI uint64
  240. SI uint64
  241. BP uint64
  242. SP uint64
  243. R8 uint64
  244. R9 uint64
  245. R10 uint64
  246. R11 uint64
  247. R12 uint64
  248. R13 uint64
  249. R14 uint64
  250. R15 uint64
  251. IP uint64
  252. FLAGS uint64
  253. CS uint64
  254. FS uint64
  255. GS uint64
  256. }
  257. type intName struct {
  258. i uint32
  259. s string
  260. }
  261. func stringName(i uint32, names []intName, goSyntax bool) string {
  262. for _, n := range names {
  263. if n.i == i {
  264. if goSyntax {
  265. return "macho." + n.s
  266. }
  267. return n.s
  268. }
  269. }
  270. return strconv.FormatUint(uint64(i), 10)
  271. }
  272. func flagName(i uint32, names []intName, goSyntax bool) string {
  273. s := ""
  274. for _, n := range names {
  275. if n.i&i == n.i {
  276. if len(s) > 0 {
  277. s += "+"
  278. }
  279. if goSyntax {
  280. s += "macho."
  281. }
  282. s += n.s
  283. i -= n.i
  284. }
  285. }
  286. if len(s) == 0 {
  287. return "0x" + strconv.FormatUint(uint64(i), 16)
  288. }
  289. if i != 0 {
  290. s += "+0x" + strconv.FormatUint(uint64(i), 16)
  291. }
  292. return s
  293. }