cle: Issue loading binary with exceptions

Heyo! So I was curious to see how angr/cle parses exceptions so I have this library:

#include <iostream>

class DinosaurException { 

public:
    int i;
    DinosaurException() {}
    ~DinosaurException() {}
};

void throw_the_exception(bool throwit) {
    if (throwit) {
        throw DinosaurException();
    }
}

void hello_dinosaur() {
    std::cout << "Hello Dinosaur!" << std::endl;
}

void log(unsigned int count) {
    std::cout << count << std::endl;
}

void catch_the_exception() {
    log(0);
    try {
        log(1);
        hello_dinosaur();
        throw_the_exception(true);
        log(2);
    } catch (const DinosaurException& e) {        
        log(3);
    }

    // more catch statements here
    log(4);
}

int main() {
    catch_the_exception();
    return 0;
}

And then I build it:

g++ -g -c exception.cpp

And then try to load it:

import cle
path = sys.argv[1]
if not os.path.exists(path):
    sys.exit('%s does not exist' % path)
ld = cle.Loader(path, load_debug_info=True, auto_load_libs=False)

And I get the following error:

Traceback (most recent call last):
  File "dev.py", line 11, in <module>
    ld = cle.Loader(path, load_debug_info=True, auto_load_libs=False)
  File "/home/vanessa/Desktop/Code/cle/cle/loader.py", line 133, in __init__
    self.initial_load_objects = self._internal_load(main_binary, *preload_libs, *force_load_libs, preloading=(main_binary, *preload_libs))
  File "/home/vanessa/Desktop/Code/cle/cle/loader.py", line 673, in _internal_load
    obj = self._load_object_isolated(main_spec)
  File "/home/vanessa/Desktop/Code/cle/cle/loader.py", line 855, in _load_object_isolated
    result = backend_cls(binary, binary_stream, is_main_bin=self.main_object is None, loader=self, **options)
  File "/home/vanessa/Desktop/Code/cle/cle/backends/elf/elf.py", line 178, in __init__
    self._load_exception_handling(dwarf)
  File "/home/vanessa/Desktop/Code/cle/cle/backends/elf/elf.py", line 540, in _load_exception_handling
    lsda_exception_table = lsda.parse_lsda(entry.lsda_pointer, file_offset)
  File "/home/vanessa/Desktop/Code/cle/cle/backends/elf/lsda.py", line 97, in parse_lsda
    header = self._parse_lsda_header()
  File "/home/vanessa/Desktop/Code/cle/cle/backends/elf/lsda.py", line 127, in _parse_lsda_header
    raise NotImplementedError("Unsupported modifier %#x." % modifier)
NotImplementedError: Unsupported modifier 0xf0.

I’m guessing there is something specific about my example program (e.g., the “unsupported modifier” I see above) and for the time being I’ll try to inspect exceptions in another program! But I’m wondering what the specific issue is above and if I can fix it?

About this issue

  • Original URL
  • State: closed
  • Created 2 years ago
  • Comments: 18 (6 by maintainers)

Most upvoted comments

Yes - since we’re hardcoding properties about the binaries themselves in our testcases (occasionally to the level of individual instruction addresses), we can’t rely on compilers to not change this stuff out from under us!

The expectation is that the binaries repository is cloned into the same directory that cle or angr or whatever is. We have the angr-dev repository to set up this structure. The testcases manually reach outside their repository to get to these files. Here is a good example of a testcase using that model.

we generally like tests that are as end-to-end as possible around here, so if you have some notion of a set of “in the wild” inputs and a way to validate the outputs of processing those inputs, that would be totally acceptable.