desc.c v0.62

Chuck Ebbert (76306.1226@compuserve.com)
Wed, 30 Apr 2003 10:32:30 -0400


#define PROG_NAME "desc"
#define PROG_TITLE "dump i386 CPU descriptor tables"
#define VERSION "0.62"
/* v0.62 : almost all TSS fields, all Pentium segtypes */
#define AUTHOR "Chuck Ebbert <76306.1226@compuserve.com>"
#define COPYRIGHT "Copyright (c) 2003 Chuck Ebbert"
#define LICENSE "Released under the GPL"

#include <stdio.h>
#include <fcntl.h>
#include <sys/types.h>

typedef struct { /* from Linux */
unsigned short back_link,__blh;
unsigned long esp0;
unsigned short ss0,__ss0h;
unsigned long esp1;
unsigned short ss1,__ss1h;
unsigned long esp2;
unsigned short ss2,__ss2h;
unsigned long __cr3;
unsigned long eip;
unsigned long eflags;
unsigned long eax,ecx,edx,ebx;
unsigned long esp;
unsigned long ebp;
unsigned long esi;
unsigned long edi;
unsigned short es, __esh;
unsigned short cs, __csh;
unsigned short ss, __ssh;
unsigned short ds, __dsh;
unsigned short fs, __fsh;
unsigned short gs, __gsh;
unsigned short ldt, __ldth;
unsigned short trace, bitmap;
} __attribute__ ((packed)) tss_t;

typedef struct {
unsigned short limit;
unsigned int base;
} __attribute__ ((packed)) dtr_t;

typedef struct {
unsigned short off1;
unsigned short sel;
unsigned char none,flags;
unsigned short off2;
} __attribute__ ((packed)) gate_desc_t;

typedef struct {
unsigned a,b;
} __attribute__ ((packed)) desc_t;

/* read/write from kmem */
#define BUILD_IO_FN(fn_name, fn_fn) \
static int fn_name (int fd, int offset, void *buf, int size) { \
if (lseek(fd, offset, 0) != offset) return 0; \
if (fn_fn(fd, buf, size) != size) return 0; \
return size; \
}
BUILD_IO_FN(rkm, read)
BUILD_IO_FN(wkm, write)

#define perr(err) { perror(err), exit(1); }
/* read/write wrapper with err handling */
#define xkm(f, p1, p2, p3, p4, msg) { \
int _p4 = (p4); if ((f)((p1), (p2), (p3), _p4) != _p4) perr(msg); }
#define TEST_BIT(v,b) ( !!((v) & (1 << (b))) )
#define nl printf("\n")

int kmem;

void dump_sel (char *nm, unsigned short s) {
printf("%s:%04x <%s#%02d,RPL%d>",
nm, s, (s & 4) ? "LDT" : "GDT", s >> 3, s & 3);
}
void dump_table (char * name, unsigned base, unsigned num) {
unsigned cdt, db, dl, a, b, t, i, f;
desc_t desc;
gate_desc_t *gate = (gate_desc_t *)&desc; /* FIXME */
tss_t tss;

printf(" %s at %08x, %d entries:\n\n", name, base, num);
for (i = 0; i < num; i++) {
xkm(rkm, kmem, base + 8*i, &desc, sizeof(desc), "rkm gdtldt");
a = desc.a, b = desc.b, f = (b & 0xf0ff00) >> 8, t = f & 0x1f;
if (!a & !b) continue; /* empty */
if ((t & 0x04) == 0x04) { /* gate */
f = gate->flags, t = f & 0x1f;
printf("%s#%3d: ", name, i);
dump_sel("sel", gate->sel);
printf(" off:%08x flags:%02x <%s,DPL%d,%s Gate>\n",
(unsigned)((gate->off2 << 16) | gate->off1),
f, TEST_BIT(f,7) ? "P" : "N", (f & 0x60) >> 5,
(t == 0x05) ? "Task" :
(t == 0x0c) ? "32b,Call" :
(t == 0x0e) ? "32b,Intr" :
(t == 0x0f) ? "32b,Trap" :
(t == 0x04) ? "16b,Call" :
(t == 0x06) ? "16b,Intr" :
(t == 0x07) ? "16b,Trap" :
"Unknown");
continue;
}
cdt = f & 0x401e; /* code/data type, base, limit */
dl = (a & 0xffff) | (b & 0x0f0000);
db = (b & 0xff000000) | ((b & 0xff) << 16) | (a >> 16);
printf("%s#%3d: base:%08x limit:%05x%s"
" flags:%04x <%s,DPL%d,%s>\n",
name, i, db, dl, TEST_BIT(b,23) ? "fff" : " ",
f, TEST_BIT(b,15) ? "P" : "N", (b & 0x6000) >> 13,
(t == 0x01) ? "16b,Avail TSS" :
(t == 0x02) ? "LDT" :
(t == 0x03) ? "16b,Busy TSS" :
(t == 0x09) ? "32b,Avail TSS" :
(t == 0x0b) ? "32b,Busy TSS" :
(cdt == 0x0010) ? "16b,RO Data" :
(cdt == 0x0012) ? "16b,RW Data" :
(cdt == 0x0014) ? "16b,RO Expd Data" :
(cdt == 0x0016) ? "16b,RW Expd Data" :
(cdt == 0x0018) ? "16b,XO Code" :
(cdt == 0x001a) ? "16b,RX Code" :
(cdt == 0x001c) ? "16b,XO Conf Code" :
(cdt == 0x001e) ? "16b,RX Conf Code" :
(cdt == 0x4010) ? "32b,RO Data" :
(cdt == 0x4012) ? "32b,RW Data" :
(cdt == 0x4014) ? "32b,RO Expd Data" :
(cdt == 0x4016) ? "32b,RW Expd Data" :
(cdt == 0x4018) ? "32b,XO Code" :
(cdt == 0x401a) ? "32b,RX Code" :
(cdt == 0x401c) ? "32b,XO Conf Code" :
(cdt == 0x401e) ? "32b,RX Conf Code" :
"Unknown");
if (t == 0x02)
nl, dump_table(" LDT", db, (dl + 1) >> 3);
if ((t == 0x09) | (t == 0x0b)) {
xkm(rkm, kmem, db, &tss, sizeof(tss), "rkm tss");
printf("\n TSS at %08x, %d bytes:\n\n", db, dl + 1);
dump_sel(" CS", tss.cs);
printf(" EIP:%08x eflags:%08x\n",
tss.eip, tss.eflags);
dump_sel(" SS0", tss.ss0);
printf(" ESP0:%08x\n", tss.esp0);
dump_sel(" SS1", tss.ss1);
printf(" ESP1:%08x\n", tss.esp1);
dump_sel(" SS2", tss.ss2);
printf(" ESP2:%08x\n", tss.esp2);
dump_sel(" SS", tss.ss);
printf(" ESP:%08x\n", tss.esp);
dump_sel(" DS", tss.ds);
dump_sel(" ES", tss.es), nl;
dump_sel(" FS", tss.fs);
dump_sel(" GS", tss.gs), nl;
printf(" EAX:%08x EBX:%08x ECX:%08x EDX:%08x\n",
tss.eax, tss.ebx, tss.ecx, tss.edx);
printf(" ESI:%08x EDI:%08x EBP:%08x\n",
tss.esi, tss.edi, tss.ebp);
dump_sel(" LDT", tss.ldt);
printf(" CR3:%08x\n\n", tss.__cr3);
}
}
nl;
}
main() {
dtr_t dtr;

printf(PROG_NAME " v" VERSION " -- " PROG_TITLE "\n\n");
kmem = open("/dev/kmem", O_RDONLY);
if (kmem < 0) perr("open /dev/kmem");

asm("sgdt %0" : "=m" (dtr));
dump_table("GDT", dtr.base, (dtr.limit + 1) >> 3);
asm("sidt %0" : "=m" (dtr));
dump_table("IDT", dtr.base, (dtr.limit + 1) >> 3);

close(kmem);
}
------
Chuck
-
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
Please read the FAQ at http://www.tux.org/lkml/