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 "
|
help=("Force re-generation of the output files, even "
|
||||||
"when those files are newer than the target "
|
"when those files are newer than the target "
|
||||||
"ELF."))
|
"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
|
# c_opt_level
|
||||||
opt_level_grp = parser.add_mutually_exclusive_group()
|
opt_level_grp = parser.add_mutually_exclusive_group()
|
||||||
opt_level_grp.add_argument('-O0', action='store_const', const='-O0',
|
opt_level_grp.add_argument('-O0', action='store_const', const='-O0',
|
||||||
|
@ -197,6 +202,8 @@ def main():
|
||||||
for opt in DW_ASSEMBLY_OPTS:
|
for opt in DW_ASSEMBLY_OPTS:
|
||||||
if opt in args and args_dict[opt] is not None:
|
if opt in args and args_dict[opt] is not None:
|
||||||
dwarf_assembly_opts.append(DW_ASSEMBLY_OPTS[opt])
|
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:
|
for obj in args.object:
|
||||||
args.gen_func(obj, args, dwarf_assembly_opts)
|
args.gen_func(obj, args, dwarf_assembly_opts)
|
||||||
|
|
|
@ -5,3 +5,5 @@ typedef struct {
|
||||||
} unwind_context_t;
|
} unwind_context_t;
|
||||||
|
|
||||||
typedef unwind_context_t (*_fde_func_t)(unwind_context_t, uintptr_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) {
|
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 "
|
os << "unwind_context_t "
|
||||||
<< name
|
<< 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"
|
<< "\tunwind_context_t out_ctx;\n"
|
||||||
<< "\tswitch(pc) {" << endl;
|
<< "\tswitch(pc) {" << endl;
|
||||||
}
|
}
|
||||||
|
@ -168,11 +172,19 @@ void CodeGenerator::gen_of_reg(const SimpleDwarf::DwRegister& reg) {
|
||||||
os << ctx_of_dw_name(reg.reg)
|
os << ctx_of_dw_name(reg.reg)
|
||||||
<< " + (" << reg.offset << ")";
|
<< " + (" << reg.offset << ")";
|
||||||
break;
|
break;
|
||||||
case SimpleDwarf::DwRegister::REG_CFA_OFFSET:
|
case SimpleDwarf::DwRegister::REG_CFA_OFFSET: {
|
||||||
os << "*((uintptr_t*)(out_ctx.rsp + ("
|
if(settings::enable_deref_arg) {
|
||||||
<< reg.offset
|
os << "deref(out_ctx.rsp + ("
|
||||||
<< ")))";
|
<< reg.offset
|
||||||
|
<< "))";
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
os << "*((uintptr_t*)(out_ctx.rsp + ("
|
||||||
|
<< reg.offset
|
||||||
|
<< ")))";
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
|
}
|
||||||
case SimpleDwarf::DwRegister::REG_NOT_IMPLEMENTED:
|
case SimpleDwarf::DwRegister::REG_NOT_IMPLEMENTED:
|
||||||
os << "0; assert(0)";
|
os << "0; assert(0)";
|
||||||
break;
|
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.
|
which is the PC in little endian.
|
||||||
|
|
||||||
`--pc-list PC_LIST_FILE_PATH`
|
`--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];
|
settings::pc_list = argv[option_pos];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
else if(option == "--enable-deref-arg") {
|
||||||
|
settings::enable_deref_arg = true;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if(!seen_switch_gen_policy) {
|
if(!seen_switch_gen_policy) {
|
||||||
|
|
|
@ -3,4 +3,5 @@
|
||||||
namespace settings {
|
namespace settings {
|
||||||
SwitchGenerationPolicy switch_generation_policy = SGP_SwitchPerFunc;
|
SwitchGenerationPolicy switch_generation_policy = SGP_SwitchPerFunc;
|
||||||
std::string pc_list = "";
|
std::string pc_list = "";
|
||||||
|
bool enable_deref_arg = false;
|
||||||
}
|
}
|
||||||
|
|
|
@ -15,4 +15,5 @@ namespace settings {
|
||||||
|
|
||||||
extern SwitchGenerationPolicy switch_generation_policy;
|
extern SwitchGenerationPolicy switch_generation_policy;
|
||||||
extern std::string pc_list;
|
extern std::string pc_list;
|
||||||
|
extern bool enable_deref_arg;
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue