Add and implement --enable-deref-arg feature

This commit is contained in:
Théophile Bastian 2018-06-01 19:46:43 +02:00
parent df2d6179a8
commit 7960b5ba08
7 changed files with 49 additions and 5 deletions

View file

@ -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)

View file

@ -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);

View file

@ -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:
os << "*((uintptr_t*)(out_ctx.rsp + ("
<< reg.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;

View file

@ -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`

View file

@ -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) {

View file

@ -3,4 +3,5 @@
namespace settings {
SwitchGenerationPolicy switch_generation_policy = SGP_SwitchPerFunc;
std::string pc_list = "";
bool enable_deref_arg = false;
}

View file

@ -15,4 +15,5 @@ namespace settings {
extern SwitchGenerationPolicy switch_generation_policy;
extern std::string pc_list;
extern bool enable_deref_arg;
}