github.com/transparency-dev/armored-witness-os@v0.1.3-0.20240514084412-27eef7325168/trusted_os/debug.go (about) 1 // Copyright 2022 The Armored Witness OS authors. 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 15 //go:build debug 16 // +build debug 17 18 package main 19 20 import ( 21 "bytes" 22 "debug/elf" 23 "debug/gosym" 24 "errors" 25 "fmt" 26 "log" 27 _ "unsafe" 28 29 "github.com/usbarmory/tamago/arm" 30 usbarmory "github.com/usbarmory/tamago/board/usbarmory/mk2" 31 "github.com/usbarmory/tamago/soc/nxp/usb" 32 33 "github.com/usbarmory/GoTEE/monitor" 34 usbserial "github.com/usbarmory/imx-usbserial" 35 36 "github.com/smallnest/ringbuffer" 37 ) 38 39 const debug = true 40 41 var serial *usbserial.UART 42 var logBuffer *ringbuffer.RingBuffer 43 44 func init() { 45 // TODO(al): Probably want to reinstate this check after wave0! 46 /* 47 if imx6ul.SNVS.Available() { 48 panic("fatal error, debug firmware not allowed on secure booted units") 49 } 50 */ 51 logBuffer = ringbuffer.New(1 << 20) 52 } 53 54 //go:linkname printk runtime.printk 55 func printk(c byte) { 56 usbarmory.UART2.Tx(c) 57 logBuffer.WriteByte(c) 58 59 if serial != nil { 60 serial.WriteByte(c) 61 } 62 } 63 64 func getConsoleLogs() []byte { 65 return logBuffer.Bytes() 66 } 67 68 func configureUART(device *usb.Device) (err error) { 69 if LAN == nil { 70 return 71 } 72 73 serial = &usbserial.UART{ 74 Device: device, 75 } 76 77 return serial.Init() 78 } 79 80 func fileLine(buf []byte, pc uint32) (s string) { 81 exe, err := elf.NewFile(bytes.NewReader(buf)) 82 83 if err != nil { 84 return 85 } 86 87 addr := exe.Section(".text").Addr 88 89 lineTableData, err := exe.Section(".gopclntab").Data() 90 91 if err != nil { 92 return 93 } 94 95 lineTable := gosym.NewLineTable(lineTableData, addr) 96 97 if err != nil { 98 return 99 } 100 101 symTableData, err := exe.Section(".gosymtab").Data() 102 103 if err != nil { 104 return 105 } 106 107 symTable, err := gosym.NewTable(symTableData, lineTable) 108 109 if err != nil { 110 return 111 } 112 113 file, line, _ := symTable.PCToLine(uint64(pc)) 114 115 return fmt.Sprintf("%s:%d", file, line) 116 } 117 118 func lookupSym(buf []byte, name string) (*elf.Symbol, error) { 119 f, err := elf.NewFile(bytes.NewReader(buf)) 120 121 if err != nil { 122 return nil, err 123 } 124 125 syms, err := f.Symbols() 126 127 if err != nil { 128 return nil, err 129 } 130 131 for _, sym := range syms { 132 if sym.Name == name { 133 return &sym, nil 134 } 135 } 136 137 return nil, errors.New("symbol not found") 138 } 139 140 // segfault schedules the execution context to its fatal error function in 141 // order to have applet dump its own stack trace and exit. The target must be a 142 // GOOS=tamago applet which imports the runtime.CallOnG0 symbol, runtime.Exit 143 // must be set to graceful termination. 144 // 145 // Example of required applet main statements: 146 // 147 // ``` 148 // 149 // func init() { 150 // runtime.Exit = applet.Exit 151 // ... 152 // } 153 // 154 // func main() { 155 // ... 156 // runtime.CallOnG0() 157 // } 158 // 159 // ``` 160 func segfault(buf []byte, ctx *monitor.ExecCtx) (err error) { 161 var sym *elf.Symbol 162 163 if sym, err = lookupSym(taELF, "runtime.fatalthrow"); err != nil { 164 return fmt.Errorf("could not find runtime.fatalthrow symbol, %v", err) 165 } 166 167 ctx.R0 = uint32(ctx.ExceptionVector) 168 ctx.R1 = uint32(sym.Value) 169 ctx.R2 = 0 170 ctx.R3 = ctx.R15 171 172 if sym, err = lookupSym(taELF, "runtime.CallOnG0"); err != nil { 173 return fmt.Errorf("could not find runtime.CallOnG0 symbol, %v", err) 174 } 175 176 ctx.R15 = uint32(sym.Value) 177 178 log.Printf("SM invoking applet %s handler pc:%#.8x", arm.VectorName(ctx.ExceptionVector), ctx.R3) 179 180 err = ctx.Run() 181 182 log.Printf("SM applet stopped sp:%#.8x lr:%#.8x pc:%#.8x err:%v", ctx.R13, ctx.R14, ctx.R15, err) 183 184 return 185 } 186 187 func inspect(buf []byte, ctx *monitor.ExecCtx) (err error) { 188 log.Printf("PC\t%s", fileLine(buf, ctx.R15)) // PC 189 log.Printf("LR\t%s", fileLine(buf, ctx.R14)) // LR 190 191 switch ctx.ExceptionVector { 192 case arm.UNDEFINED, arm.PREFETCH_ABORT, arm.DATA_ABORT: 193 return segfault(buf, ctx) 194 } 195 196 return 197 }