1 /* 2 * Dwarf data format parsing routines. 3 */ 4 5 #include <precomp.h> 6 7 #define NDEBUG 8 #include <debug.h> 9 10 ulong 11 dwarfget1(DwarfBuf *b) 12 { 13 if(b->p==nil || b->p+1 > b->ep){ 14 b->p = nil; 15 return 0; 16 } 17 return *b->p++; 18 } 19 20 int 21 dwarfgetn(DwarfBuf *b, uchar *a, int n) 22 { 23 if(b->p==nil || b->p+n > b->ep){ 24 b->p = nil; 25 memset(a, 0, n); 26 return -1; 27 } 28 memmove(a, b->p, n); 29 b->p += n; 30 return 0; 31 } 32 33 uchar* 34 dwarfgetnref(DwarfBuf *b, ulong n) 35 { 36 uchar *p; 37 38 if(b->p==nil || b->p+n > b->ep){ 39 b->p = nil; 40 return nil; 41 } 42 p = b->p; 43 b->p += n; 44 return p; 45 } 46 47 char* 48 dwarfgetstring(DwarfBuf *b) 49 { 50 char *s; 51 52 if(b->p == nil) 53 return nil; 54 s = (char*)b->p; 55 while(b->p < b->ep && *b->p) 56 b->p++; 57 if(b->p >= b->ep){ 58 b->p = nil; 59 return nil; 60 } 61 b->p++; 62 return s; 63 } 64 65 void 66 dwarfskip(DwarfBuf *b, int n) 67 { 68 if(b->p==nil || b->p+n > b->ep) 69 b->p = nil; 70 else 71 b->p += n; 72 } 73 74 ulong 75 dwarfget2(DwarfBuf *b) 76 { 77 ulong v; 78 79 if(b->p==nil || b->p+2 > b->ep){ 80 b->p = nil; 81 return 0; 82 } 83 v = b->d->pe->e2(b->p); 84 b->p += 2; 85 return v; 86 } 87 88 ulong 89 dwarfget4(DwarfBuf *b) 90 { 91 ulong v; 92 93 if(b->p==nil || b->p+4 > b->ep){ 94 b->p = nil; 95 return 0; 96 } 97 v = b->d->pe->e4(b->p); 98 b->p += 4; 99 return v; 100 } 101 102 uvlong 103 dwarfget8(DwarfBuf *b) 104 { 105 uvlong v; 106 107 if(b->p==nil || b->p+8 > b->ep){ 108 b->p = nil; 109 return 0; 110 } 111 v = b->d->pe->e8(b->p); 112 b->p += 8; 113 return v; 114 } 115 116 ulong 117 dwarfgetaddr(DwarfBuf *b) 118 { 119 static int nbad; 120 121 if(b->addrsize == 0) 122 b->addrsize = b->d->addrsize; 123 124 switch(b->addrsize){ 125 case 1: 126 return dwarfget1(b); 127 case 2: 128 return dwarfget2(b); 129 case 4: 130 return dwarfget4(b); 131 case 8: 132 return dwarfget8(b); 133 default: 134 if(++nbad == 1) 135 werrstr("dwarf: unexpected address size %lud in dwarfgetaddr", b->addrsize); 136 b->p = nil; 137 return 0; 138 } 139 } 140 141 int n1, n2, n3, n4, n5; 142 143 /* An inline function picks off the calls to dwarfget128 for 1-byte encodings, 144 * more than by far the common case (99.999% on most binaries!). */ 145 ulong 146 dwarfget128(DwarfBuf *b) 147 { 148 static int nbad; 149 ulong c, d; 150 151 if(b->p == nil) 152 return 0; 153 c = *b->p++; 154 if(!(c&0x80)) 155 {n1++; 156 return c; 157 } 158 c &= ~0x80; 159 d = *b->p++; 160 c |= (d&0x7F)<<7; 161 if(!(d&0x80)) 162 {n2++; 163 return c; 164 } 165 d = *b->p++; 166 c |= (d&0x7F)<<14; 167 if(!(d&0x80)) 168 {n3++; 169 return c; 170 } 171 d = *b->p++; 172 c |= (d&0x7F)<<21; 173 if(!(d&0x80)) 174 {n4++; 175 return c; 176 } 177 d = *b->p++; 178 c |= (d&0x7F)<<28; 179 if(!(d&0x80)) 180 {n5++; 181 return c; 182 } 183 while(b->p<b->ep && *b->p&0x80) 184 b->p++; 185 if(++nbad == 1) 186 werrstr("dwarf: overflow during parsing of uleb128 integer"); 187 return c; 188 } 189 190 long 191 dwarfget128s(DwarfBuf *b) 192 { 193 int nb, c; 194 ulong v; 195 static int nbad; 196 197 v = 0; 198 nb = 0; 199 if(b->p==nil) 200 return 0; 201 while(b->p<b->ep){ 202 c = *b->p++; 203 v |= (c & 0x7F)<<nb; 204 nb += 7; 205 if(!(c&0x80)) 206 break; 207 } 208 if(v&(1<<(nb-1))) 209 v |= ~(((ulong)1<<nb)-1); 210 if(nb > 8*sizeof(ulong)){ 211 if(0) 212 if(++nbad == 1) 213 werrstr("dwarf: overflow during parsing of sleb128 integer: got %d bits", nb); 214 } 215 return v; 216 } 217 218 219