1 use gdbstub::target; 2 use gdbstub::target::TargetError; 3 use gdbstub::target::TargetResult; 4 5 use super::copy_range_to_buf; 6 use crate::emu::Emu; 7 8 impl target::ext::target_description_xml_override::TargetDescriptionXmlOverride for Emu { target_description_xml( &self, annex: &[u8], offset: u64, length: usize, buf: &mut [u8], ) -> TargetResult<usize, Self>9 fn target_description_xml( 10 &self, 11 annex: &[u8], 12 offset: u64, 13 length: usize, 14 buf: &mut [u8], 15 ) -> TargetResult<usize, Self> { 16 let xml = match annex { 17 b"target.xml" => TARGET_XML.trim(), 18 b"extra.xml" => EXTRA_XML.trim(), 19 _ => return Err(TargetError::NonFatal), 20 }; 21 22 Ok(copy_range_to_buf( 23 xml.trim().as_bytes(), 24 offset, 25 length, 26 buf, 27 )) 28 } 29 } 30 31 const TARGET_XML: &str = r#" 32 <?xml version="1.0"?> 33 <!DOCTYPE target SYSTEM "gdb-target.dtd"> 34 <target version="1.0"> 35 <architecture>armv4t</architecture> 36 <feature name="org.gnu.gdb.arm.core"> 37 <vector id="padding" type="uint32" count="25"/> 38 39 <reg name="r0" bitsize="32" type="uint32"/> 40 <reg name="r1" bitsize="32" type="uint32"/> 41 <reg name="r2" bitsize="32" type="uint32"/> 42 <reg name="r3" bitsize="32" type="uint32"/> 43 <reg name="r4" bitsize="32" type="uint32"/> 44 <reg name="r5" bitsize="32" type="uint32"/> 45 <reg name="r6" bitsize="32" type="uint32"/> 46 <reg name="r7" bitsize="32" type="uint32"/> 47 <reg name="r8" bitsize="32" type="uint32"/> 48 <reg name="r9" bitsize="32" type="uint32"/> 49 <reg name="r10" bitsize="32" type="uint32"/> 50 <reg name="r11" bitsize="32" type="uint32"/> 51 <reg name="r12" bitsize="32" type="uint32"/> 52 <reg name="sp" bitsize="32" type="data_ptr"/> 53 <reg name="lr" bitsize="32"/> 54 <reg name="pc" bitsize="32" type="code_ptr"/> 55 56 <!-- 57 For some reason, my version of `gdb-multiarch` doesn't seem to 58 respect "regnum", and will not parse this custom target.xml unless I 59 manually include the padding bytes in the target description. 60 61 On the bright side, AFAIK, there aren't all that many architectures 62 that use padding bytes. Heck, the only reason armv4t uses padding is 63 for historical reasons (see comment below). 64 65 Odds are if you're defining your own custom arch, you won't run into 66 this issue, since you can just lay out all the registers in the 67 correct order. 68 --> 69 <reg name="padding" type="padding" bitsize="32"/> 70 71 <!-- The CPSR is register 25, rather than register 16, because 72 the FPA registers historically were placed between the PC 73 and the CPSR in the "g" packet. --> 74 <reg name="cpsr" bitsize="32" regnum="25"/> 75 </feature> 76 <xi:include href="extra.xml"/> 77 </target> 78 "#; 79 80 const EXTRA_XML: &str = r#" 81 <?xml version="1.0"?> 82 <!DOCTYPE target SYSTEM "gdb-target.dtd"> 83 <feature name="custom-armv4t-extension"> 84 <!-- 85 maps to a simple scratch register within the emulator. the GDB 86 client can read the register using `p $custom` and set it using 87 `set $custom=1337` 88 --> 89 <reg name="custom" bitsize="32" type="uint32"/> 90 91 <!-- 92 pseudo-register that return the current time when read. 93 94 notably, i've set up the target to NOT send this register as part of 95 the regular register list, which means that GDB will fetch/update 96 this register via the 'p' and 'P' packets respectively 97 --> 98 <reg name="time" bitsize="32" type="uint32"/> 99 100 <!-- 101 pseudo-register that is always unavailable. 102 103 it is supposed to be reported as 'x'-ed bytes in replies to 'p' packets 104 and shown by the GDB client as "<unavailable>". 105 --> 106 <reg name="unavailable" bitsize="32" type="uint32"/> 107 </feature> 108 "#; 109