Add and implement --enable-deref-arg feature
This commit is contained in:
parent
df2d6179a8
commit
7960b5ba08
7 changed files with 49 additions and 5 deletions
|
@ -148,6 +148,11 @@ def process_args():
|
|||
help=("Force re-generation of the output files, even "
|
||||
"when those files are newer than the target "
|
||||
"ELF."))
|
||||
parser.add_argument('--enable-deref-arg', action='store_true',
|
||||
help=("Pass the `--enable-deref-arg` to "
|
||||
"dwarf-assembly, enabling an extra `deref` "
|
||||
"argument for each lookup function, allowing "
|
||||
"to work on remote address spaces."))
|
||||
# c_opt_level
|
||||
opt_level_grp = parser.add_mutually_exclusive_group()
|
||||
opt_level_grp.add_argument('-O0', action='store_const', const='-O0',
|
||||
|
@ -197,6 +202,8 @@ def main():
|
|||
for opt in DW_ASSEMBLY_OPTS:
|
||||
if opt in args and args_dict[opt] is not None:
|
||||
dwarf_assembly_opts.append(DW_ASSEMBLY_OPTS[opt])
|
||||
if args.enable_deref_arg:
|
||||
dwarf_assembly_opts.append('--enable-deref-arg')
|
||||
|
||||
for obj in args.object:
|
||||
args.gen_func(obj, args, dwarf_assembly_opts)
|
||||
|
|
|
@ -5,3 +5,5 @@ typedef struct {
|
|||
} unwind_context_t;
|
||||
|
||||
typedef unwind_context_t (*_fde_func_t)(unwind_context_t, uintptr_t);
|
||||
|
||||
typedef uintptr_t (*deref_func_t)(uintptr_t);
|
||||
|
|
|
@ -65,9 +65,13 @@ void CodeGenerator::gen_of_dwarf() {
|
|||
}
|
||||
|
||||
void CodeGenerator::gen_unwind_func_header(const std::string& name) {
|
||||
string deref_arg;
|
||||
if(settings::enable_deref_arg)
|
||||
deref_arg = ", deref_func_t deref";
|
||||
|
||||
os << "unwind_context_t "
|
||||
<< name
|
||||
<< "(unwind_context_t ctx, uintptr_t pc) {\n"
|
||||
<< "(unwind_context_t ctx, uintptr_t pc" << deref_arg << ") {\n"
|
||||
<< "\tunwind_context_t out_ctx;\n"
|
||||
<< "\tswitch(pc) {" << endl;
|
||||
}
|
||||
|
@ -168,11 +172,19 @@ void CodeGenerator::gen_of_reg(const SimpleDwarf::DwRegister& reg) {
|
|||
os << ctx_of_dw_name(reg.reg)
|
||||
<< " + (" << reg.offset << ")";
|
||||
break;
|
||||
case SimpleDwarf::DwRegister::REG_CFA_OFFSET:
|
||||
case SimpleDwarf::DwRegister::REG_CFA_OFFSET: {
|
||||
if(settings::enable_deref_arg) {
|
||||
os << "deref(out_ctx.rsp + ("
|
||||
<< reg.offset
|
||||
<< "))";
|
||||
}
|
||||
else {
|
||||
os << "*((uintptr_t*)(out_ctx.rsp + ("
|
||||
<< reg.offset
|
||||
<< ")))";
|
||||
}
|
||||
break;
|
||||
}
|
||||
case SimpleDwarf::DwRegister::REG_NOT_IMPLEMENTED:
|
||||
os << "0; assert(0)";
|
||||
break;
|
||||
|
|
|
@ -23,3 +23,20 @@ a list of all PCs in the ELF. The file contains one 8-bytes chunk per PC,
|
|||
which is the PC in little endian.
|
||||
|
||||
`--pc-list PC_LIST_FILE_PATH`
|
||||
|
||||
### Dereferencing function
|
||||
|
||||
The lookup functions can also take an additional argument, a pointer to a
|
||||
function of prototype
|
||||
|
||||
```C
|
||||
uintptr_t deref(uintptr_t address)
|
||||
```
|
||||
|
||||
that will, in spirit, contain a `return *((uintptr_t*)address);`.
|
||||
|
||||
This argument can be used to work on remote address spaces instead of local
|
||||
address spaces, eg. to work with `libunwind`.
|
||||
|
||||
To enable the presence of this argument, you must pass the option
|
||||
`--enable-deref-arg`
|
||||
|
|
|
@ -56,6 +56,10 @@ MainOptions options_parse(int argc, char** argv) {
|
|||
settings::pc_list = argv[option_pos];
|
||||
}
|
||||
}
|
||||
|
||||
else if(option == "--enable-deref-arg") {
|
||||
settings::enable_deref_arg = true;
|
||||
}
|
||||
}
|
||||
|
||||
if(!seen_switch_gen_policy) {
|
||||
|
|
|
@ -3,4 +3,5 @@
|
|||
namespace settings {
|
||||
SwitchGenerationPolicy switch_generation_policy = SGP_SwitchPerFunc;
|
||||
std::string pc_list = "";
|
||||
bool enable_deref_arg = false;
|
||||
}
|
||||
|
|
|
@ -15,4 +15,5 @@ namespace settings {
|
|||
|
||||
extern SwitchGenerationPolicy switch_generation_policy;
|
||||
extern std::string pc_list;
|
||||
extern bool enable_deref_arg;
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue