aboutsummaryrefslogtreecommitdiff
path: root/src/libmach/dwarfget.c
diff options
context:
space:
mode:
authorrsc <devnull@localhost>2004-04-19 19:29:25 +0000
committerrsc <devnull@localhost>2004-04-19 19:29:25 +0000
commita84cbb2a17c9d0b88c561d5b7cb50d79a19e7c46 (patch)
tree59a0e921597e5aa53e83d487c16727a7bf01547a /src/libmach/dwarfget.c
parent0e3cc9f456ea49919459bf1164d0c8309a6134fa (diff)
downloadplan9port-a84cbb2a17c9d0b88c561d5b7cb50d79a19e7c46.tar.gz
plan9port-a84cbb2a17c9d0b88c561d5b7cb50d79a19e7c46.tar.bz2
plan9port-a84cbb2a17c9d0b88c561d5b7cb50d79a19e7c46.zip
libmach
Diffstat (limited to 'src/libmach/dwarfget.c')
-rw-r--r--src/libmach/dwarfget.c217
1 files changed, 217 insertions, 0 deletions
diff --git a/src/libmach/dwarfget.c b/src/libmach/dwarfget.c
new file mode 100644
index 00000000..da8558c4
--- /dev/null
+++ b/src/libmach/dwarfget.c
@@ -0,0 +1,217 @@
+/*
+ * Dwarf data format parsing routines.
+ */
+
+#include <u.h>
+#include <libc.h>
+#include <bio.h>
+#include "elf.h"
+#include "dwarf.h"
+
+ulong
+dwarfget1(DwarfBuf *b)
+{
+ if(b->p==nil || b->p+1 > b->ep){
+ b->p = nil;
+ return 0;
+ }
+ return *b->p++;
+}
+
+int
+dwarfgetn(DwarfBuf *b, uchar *a, int n)
+{
+ if(b->p==nil || b->p+n > b->ep){
+ b->p = nil;
+ memset(a, 0, n);
+ return -1;
+ }
+ memmove(a, b->p, n);
+ b->p += n;
+ return 0;
+}
+
+uchar*
+dwarfgetnref(DwarfBuf *b, ulong n)
+{
+ uchar *p;
+
+ if(b->p==nil || b->p+n > b->ep){
+ b->p = nil;
+ return nil;
+ }
+ p = b->p;
+ b->p += n;
+ return p;
+}
+
+char*
+dwarfgetstring(DwarfBuf *b)
+{
+ char *s;
+
+ if(b->p == nil)
+ return nil;
+ s = (char*)b->p;
+ while(b->p < b->ep && *b->p)
+ b->p++;
+ if(b->p >= b->ep){
+ b->p = nil;
+ return nil;
+ }
+ b->p++;
+ return s;
+}
+
+void
+dwarfskip(DwarfBuf *b, int n)
+{
+ if(b->p==nil || b->p+n > b->ep)
+ b->p = nil;
+ else
+ b->p += n;
+}
+
+ulong
+dwarfget2(DwarfBuf *b)
+{
+ ulong v;
+
+ if(b->p==nil || b->p+2 > b->ep){
+ b->p = nil;
+ return 0;
+ }
+ v = b->d->elf->hdr.e2(b->p);
+ b->p += 2;
+ return v;
+}
+
+ulong
+dwarfget4(DwarfBuf *b)
+{
+ ulong v;
+
+ if(b->p==nil || b->p+4 > b->ep){
+ b->p = nil;
+ return 0;
+ }
+ v = b->d->elf->hdr.e4(b->p);
+ b->p += 4;
+ return v;
+}
+
+uvlong
+dwarfget8(DwarfBuf *b)
+{
+ uvlong v;
+
+ if(b->p==nil || b->p+8 > b->ep){
+ b->p = nil;
+ return 0;
+ }
+ v = b->d->elf->hdr.e8(b->p);
+ b->p += 8;
+ return v;
+}
+
+ulong
+dwarfgetaddr(DwarfBuf *b)
+{
+ static int nbad;
+
+ if(b->addrsize == 0)
+ b->addrsize = b->d->addrsize;
+
+ switch(b->addrsize){
+ case 1:
+ return dwarfget1(b);
+ case 2:
+ return dwarfget2(b);
+ case 4:
+ return dwarfget4(b);
+ case 8:
+ return dwarfget8(b);
+ default:
+ if(++nbad == 1)
+ fprint(2, "dwarf: unexpected address size %lud in dwarfgetaddr\n", b->addrsize);
+ b->p = nil;
+ return 0;
+ }
+}
+
+int n1, n2, n3, n4, n5;
+
+/* An inline function picks off the calls to dwarfget128 for 1-byte encodings,
+ * more than by far the common case (99.999% on most binaries!). */
+ulong
+dwarfget128(DwarfBuf *b)
+{
+ static int nbad;
+ ulong c, d;
+
+ if(b->p == nil)
+ return 0;
+ c = *b->p++;
+ if(!(c&0x80))
+{n1++;
+ return c;
+}
+ d = *b->p++;
+ c |= (d&0x7F)<<7;
+ if(!(d&0x80))
+{n2++;
+ return c;
+}
+ d = *b->p++;
+ c |= (d&0x7F)<<14;
+ if(!(d&0x80))
+{n3++;
+ return c;
+}
+ d = *b->p++;
+ c |= (d&0x7F)<<21;
+ if(!(d&0x80))
+{n4++;
+ return c;
+}
+ d = *b->p++;
+ c |= (d&0x7F)<<28;
+ if(!(d&0x80))
+{n5++;
+ return c;
+}
+ while(b->p<b->ep && *b->p&0x80)
+ b->p++;
+ if(++nbad == 1)
+ fprint(2, "dwarf: overflow during parsing of uleb128 integer\n");
+ return c;
+}
+
+long
+dwarfget128s(DwarfBuf *b)
+{
+ int nb, c;
+ ulong v;
+ static int nbad;
+
+ v = 0;
+ nb = 0;
+ if(b->p==nil)
+ return 0;
+ while(b->p<b->ep){
+ c = *b->p++;
+ v |= (c & 0x7F)<<nb;
+ nb += 7;
+ if(!(c&0x80))
+ break;
+ }
+ if(v&(1<<(nb-1)))
+ v |= ~(((ulong)1<<nb)-1);
+ if(nb > 8*sizeof(ulong)){
+ if(0)
+ if(++nbad == 1)
+ fprint(2, "dwarf: overflow during parsing of sleb128 integer: got %d bits\n", nb);
+ }
+ return v;
+}
+