This is the mail archive of the
frysk@sources.redhat.com
mailing list for the frysk project.
dwarf support for expressions
- From: Stan Cox <scox at redhat dot com>
- To: frysk at sources dot redhat dot com
- Date: Tue, 05 Sep 2006 13:08:55 -0400
- Subject: dwarf support for expressions
Here is what I have thus far for dwarf support just to get feedback as
to the general direction. There are still some rough edges.
Example:
% cat /home/scox/accu/src/loop.c
int j = 7;
bar ()
{
int i = 8;
while (i)
{
}
}
foo ()
{
bar ();
}
main ()
{
foo ();
}
% (hpd) attach /home/scox/accu/src/loop.x 31826
(hpd) what j
int j
(hpd) what i
int i
(hpd) print j
7
(hpd) print i
# No DW_AT_frame_base support so value is wrong
0
(hpd) assign j 9
9
(hpd) print j
# Need to actually put the value with ptrace
7
(hpd) quit
Changes:
0. Add frysk-core/frysk/cli/hpd/hpd.java
(Command line interface to CLI.java, makes testing easier)
1. frysk-core/frysk/cli/hpd/CLI.java
Add attach/detach to attach to a process
2. Move PrintHandler.java to SymTab.java
3. SymTab
A. class symTab callback to frysk-core/frysk/expr
- put not fully implemented but will be similar to get
- get implemented for static int
Need: DW_AT_frame_base support for local variables
Need: Complex addressing support
Need: add types other than int
B. class SymTab
- 'what' gives variable type
Need: Expand for more complex types
- 'print' interfaces to expr, no changes
4. frysk-core/frysk/lang/Endian.java
A. Remove and change all callers to use inua/eio/ByteOrder.java
B. Add CppSymTab interface for 3-A above
(This is independent of everything else)
5. frysk-imports/lib/dw/DwarfDie.java
A. Add getScopesVar to return dwarf scoping info
B. Add getAddr to return the address of a variable
Possibly need to refactor this to accomodate more complex address
modes
C. getType to return the type of a variable
D. fbregVariable to say if a variable is local off of frame ptr
6. frysk-imports/lib/dw/cni/DwarfDie.cxx
For 5 above
Index: frysk-core/frysk/cli/hpd/CLI.java
===================================================================
diff -u -p -r1.12 CLI.java
--- frysk-core/frysk/cli/hpd/CLI.java 14 Jul 2006 22:24:56 -0000 1.12
+++ frysk-core/frysk/cli/hpd/CLI.java 5 Sep 2006 16:33:48 -0000
@@ -48,5 +48,11 @@ import java.util.Iterator;
public class CLI
{
+ private Dwfl dwfl;
+ Proc proc;
+ Task task;
+ int pid = 0;
+ SymTab symtab;
+
/*
* Command handlers
*/
@@ -255,6 +277,55 @@ public class CLI
}
}
+ class AttachHandler implements CommandHandler
+ {
+ public void handle(Command cmd) throws ParseException
+ {
+ Vector params = cmd.getParameters();
+ String executable = "";
+
+ if (params.size() != 2)
+ {
+ cmd.getOut().println ("Usage " + cmd.getAction() +
"Executable PID");
+ return;
+ }
+ Manager.eventLoop.runPolling (5 * 1000);
+
+ executable = ((String)params.elementAt(0));
+ pid = Integer.parseInt((String)params.elementAt(1));
+
+ try {
+ Ptrace.attach(pid);
+ }
+ catch (Errno errno) {
+ addMessage(new Message("No such process.",
Message.TYPE_ERROR));
+ }
+
+ Manager.host.requestRefreshXXX (true);
+ Manager.eventLoop.runPending ();
+ proc = Manager.host.getProc (new ProcId (pid));
+ task = proc.getMainTask();
+ SymTab symtab = new SymTab(pid, proc, task);
+ }
+ }
+
+ class DetachHandler implements CommandHandler
+ {
+ public void handle(Command cmd) throws ParseException
+ {
+ Vector params = cmd.getParameters();
+ String sInput =
cmd.getFullCommand().substring(cmd.getAction().length()).trim();
+
+ if (params.size() > 0)
+ {
+ cmd.getOut().println ("Usage " + cmd.getAction());
+ return;
+ }
+
+ Manager.eventLoop.requestStop();
+ }
+ }
+
class UnaliasHandler implements CommandHandler
{
public void handle(Command cmd) throws ParseException
Index: frysk-core/frysk/cli/hpd/SymTab.java
===================================================================
// This file is part of the program FRYSK.
// ...
import ...
class symTab implements CppSymTab
{
static Map symTab = new HashMap();
public void put(String s, Variable v)
{ symTab.put(s, v);}
public Variable get(String s)
{
Dwfl dwfl;
long address;
try
{
address = SymTab.task.getIsa().pc(SymTab.task) - 1;
}
catch (TaskException tte)
{
throw new RuntimeException(tte);
}
dwfl = new Dwfl(SymTab.pid);
DwflLine line = null;
DwflDieBias bias = dwfl.getDie(address);
DwarfDie die = bias.die;
DwarfDie[] allDies = die.getScopes(die.getLowPC() - bias.bias);
String sInput = s;
DwarfDie varDie = die.getScopesVar(allDies, sInput);
long addr = varDie.getAddr();
if (varDie.fbregVariable())
{
long regval = 0;
try
{
if (MachineType.getMachineType() == MachineType.X8664)
regval = SymTab.task.getIsa().getRegisterByName("rbp").get
(SymTab.task);
else if (MachineType.getMachineType() == MachineType.IA32)
regval = SymTab.task.getIsa().getRegisterByName("ebp").get
(SymTab.task);
}
catch (TaskException tte)
{
throw new RuntimeException(tte);
}
// Need to use DW_AT_frame_base here
addr += regval;
}
ByteBuffer buffer;
buffer = new PtraceByteBuffer(SymTab.pid,
PtraceByteBuffer.Area.DATA,
0xffffffffl);
try
{
buffer = buffer.order(SymTab.task.getIsa().getByteOrder());
}
catch (TaskException tte)
{
throw new RuntimeException(tte);
}
if (varDie.getType().compareTo("int") == 0)
{
int intVal;
intVal = buffer.getInt(addr);
Variable v;
try
{
IntegerType intType = new
IntegerType(SymTab.task.getIsa().getWordSize(),
SymTab.task.getIsa().getByteOrder());
v = IntegerType.newIntegerVariable(intType, intVal);
}
catch (TaskException tte)
{
throw new RuntimeException(tte);
}
return v;
}
return null;
}
}
public class SymTab
{
static Proc proc;
static Task task;
static int pid;
static symTab hpdsymTab = new symTab();
public SymTab (int pid_p, Proc proc_p, Task task_p)
{
pid = pid_p;
proc = proc_p;
task = task_p;
}
static public void what(Command cmd) throws ParseException
{
long address;
Dwfl dwfl;
try
{
address = task.getIsa().pc(task) - 1;
}
catch (TaskException tte)
{
throw new RuntimeException(tte);
}
dwfl = new Dwfl(pid);
DwflLine line = null;
DwflDieBias bias = dwfl.getDie(address);
DwarfDie die = bias.die;
DwarfDie[] allDies = die.getScopes(die.getLowPC() - bias.bias);
String sInput = cmd.getFullCommand().substring(4).trim();
DwarfDie varDie = die.getScopesVar(allDies, sInput);
if (varDie == null)
{
System.out.println(sInput + " not found in scope.");
return;
}
long addr = varDie.getAddr();
String type = varDie.getType();
System.out.println(type + " " + varDie.getName());
}
private static final int DECIMAL = 10;
private static final int HEX = 16;
private static final int OCTAL = 8;
static public void print(Command cmd) throws ParseException
{
...Moved from PrintHandler otherwise mostly unchanged
}
}
Index: frysk-imports/lib/dw/DwarfDie.java
===================================================================
diff -u -p -r1.4 DwarfDie.java
@@ -94,10 +94,43 @@ public class DwarfDie
return dies;
}
+ public DwarfDie getScopesVar (DwarfDie[] scopes, String variable)
+ {
+ long[] vals = new long[scopes.length];
+ for(int i = 0; i < scopes.length; i++)
+ vals[i] = scopes[i].getPointer();
+
+ DwarfDie die = null;
+ long val = get_scopesvar(vals, scopes.length, variable);
+ if (val != 0)
+ die = new DwarfDie(val, this.parent);
+ return die;
+ }
+
+
+ public long getAddr ()
+ {
+ return get_addr(this.getPointer());
+ }
+
+ public String getType ()
+ {
+ return get_type(this.getPointer());
+ }
+
protected long getPointer ()
{
return this.pointer;
}
+
+ public boolean fbregVariable ()
+ {
+ long is_fb = fbreg_variable (this.getPointer());
+ if (is_fb == 1)
+ return true;
+ else
+ return false;
+ }
// protected native long dwarf_diecu();
private native long get_lowpc ();
@@ -107,4 +140,12 @@ public class DwarfDie
private native String get_diename ();
private native long[] get_scopes (long addr);
+
+ private native long get_scopesvar (long[] scopes, long nscopes,
String variable);
+
+ private native long get_addr (long addr);
+
+ private native String get_type (long addr);
+
+ private native long fbreg_variable (long addr);
}
Index: frysk-imports/lib/dw/cni/DwarfDie.cxx
===================================================================
diff -u -p -r1.3 DwarfDie.cxx
@@ -78,3 +82,96 @@ lib::dw::DwarfDie::get_scopes(jlong addr
return longs;
}
+
+Dwarf_Die *var_die;
+
+jlong
+lib::dw::DwarfDie::get_scopesvar (jlongArray scopes, jlong nscopes,
+ jstring variable)
+{
+ // alloc this in java
+ var_die = (Dwarf_Die*)malloc(sizeof(Dwarf_Die));
+
+ Dwarf_Die *dies[nscopes];
+ jlong* scopesp = elements(scopes);
+
+ for(int i = 0; i < nscopes; i++)
+ {
+ jlong dieptr = scopesp[i];
+ dies[i] = (Dwarf_Die*)dieptr;
+ }
+
+ // have this return int declaring_scope
+ int code = dwarf_getscopevar (*dies, nscopes,
+ (const char*)JvGetStringChars(variable),
+ 0, NULL, 0, 0, var_die);
+ if (code >= 0)
+ return (jlong)var_die;
+ else
+ return 0;
+}
+
+jlong
+lib::dw::DwarfDie::get_addr (jlong var_die)
+{
+ Dwarf_Die *die = (Dwarf_Die*) var_die;
+ Dwarf_Block block;
+ Dwarf_Attribute loc_attr;
+ Dwarf_Op *fb_expr;
+ size_t fb_len;
+
+ if (dwarf_attr_integrate (die, DW_AT_location, &loc_attr))
+ {
+ dwarf_formblock (&loc_attr, &block);
+ dwarf_getlocation (&loc_attr, &fb_expr, &fb_len);
+ FILE *f = fopen ("/tmp/,dwarfdie", "w");
+ fprintf (f, "fb_len %d atom %x operand %d offset %d\n",
(int)fb_len, (int)fb_expr[0].atom, (int)fb_expr[0].number,
(int)fb_expr[0].offset);
+ fclose (f);
+ return fb_expr[0].number;
+ }
+ else
+ return 0;
+}
+
+jstring
+lib::dw::DwarfDie::get_type (jlong var_die)
+{
+ Dwarf_Die *die = (Dwarf_Die*) var_die;
+ Dwarf_Die *type_die, type_mem_die;
+ Dwarf_Attribute type_attr;
+
+ if (dwarf_attr_integrate (die, DW_AT_type, &type_attr))
+ {
+ type_die = dwarf_formref_die (&type_attr, &type_mem_die);
+ if (dwarf_tag (type_die) == DW_TAG_base_type)
+ {
+ return JvNewStringLatin1
+ (dwarf_formstring (dwarf_attr_integrate
+ (type_die, DW_AT_name, &type_attr)));
+ }
+ }
+ return 0;
+}
+
+jlong
+lib::dw::DwarfDie::fbreg_variable (jlong var_die)
+{
+ Dwarf_Die *die = (Dwarf_Die*) var_die;
+ Dwarf_Block block;
+ Dwarf_Attribute loc_attr;
+ Dwarf_Op *fb_expr;
+ size_t fb_len;
+
+ if (dwarf_attr_integrate (die, DW_AT_location, &loc_attr))
+ {
+ dwarf_formblock (&loc_attr, &block);
+ dwarf_getlocation (&loc_attr, &fb_expr, &fb_len);
+ FILE *f = fopen ("/tmp/,dwarfdie", "w");
+ fprintf (f, "fb_len %d atom %x operand %d offset %d\n",
(int)fb_len, (int)fb_expr[0].atom, (int)fb_expr[0].number,
(int)fb_expr[0].offset);
+ fclose (f);
+ if (fb_expr[0].atom == DW_OP_fbreg)
+ return 1;
+ }
+ return 0;
+}
+