Skip to content

Commit

Permalink
Cleanup recursion (#6)
Browse files Browse the repository at this point in the history
* cleaning up recursive function
there might be some missing imports - need to check over again
  • Loading branch information
vsoch committed Jun 14, 2022
1 parent 653b5c3 commit e0ac5e6
Show file tree
Hide file tree
Showing 29 changed files with 5,140 additions and 3,883 deletions.
496 changes: 310 additions & 186 deletions cle/backends/elf/corpus.py

Large diffs are not rendered by default.

6 changes: 4 additions & 2 deletions cle/backends/elf/decorator.py
Original file line number Diff line number Diff line change
Expand Up @@ -38,10 +38,12 @@ def __call__(self, cls, *args, **kwargs):
# Keep track of seen by offset
cls._types_seen.add(die.offset)
typ = self.func(cls, *args, **kwargs)
if not typ:
typ = {"type": "unknown"}

# Hash id is based on hash of type content
uid = self.hash(typ)
uid = self.hash(typ)

# Top level types holds the uid -> type
cls.types[uid] = typ

Expand Down
1 change: 0 additions & 1 deletion cle/backends/elf/elf.py
Original file line number Diff line number Diff line change
Expand Up @@ -75,7 +75,6 @@ def __init__(
):
super().__init__(*args, **kwargs)
patch_undo = []
print(self.binary)
try:
self._reader = elffile.ELFFile(self._binary_stream)
list(self._reader.iter_sections())
Expand Down
5 changes: 3 additions & 2 deletions cle/backends/elf/parser/AMD64/allocators.py
Original file line number Diff line number Diff line change
Expand Up @@ -100,8 +100,9 @@ def get_register_string(self, lo, hi, param) -> str:
):
return self.fallocator.next_framebase_from_type(param)

# This should never be reached
raise RuntimeError("Unknown classification")
# This should never be reached - bug in CORE/libperl.so
# raise RuntimeError("Unknown classification")
return "unknown"

def get_next_int_register(self):
"""
Expand Down
89 changes: 77 additions & 12 deletions cle/backends/elf/parser/AMD64/classifier.py
Original file line number Diff line number Diff line change
Expand Up @@ -33,15 +33,17 @@ def classify_pointer(count):
)


def classify(typ, count=0, die=None, return_classification=False, allocator=None, types=None):
def classify(
typ, count=0, die=None, return_classification=False, allocator=None, types=None
):
"""
Main entrypoint to classify something
"""
# We need to look up types for fields, etc
types = types or {}

# Don't handle this case right now
if "class" not in typ:
if not typ or "class" not in typ or typ["class"] == "Unknown":
return

cls = None
Expand All @@ -66,6 +68,11 @@ def classify(typ, count=0, die=None, return_classification=False, allocator=None
cls = classify_union(typ, allocator=allocator, types=types)
elif typ["class"] == "Array":
cls = classify_array(typ, allocator=allocator, types=types)

# If we don't know the underlying type
if not cls:
return

elif typ["class"] == "Class":
cls = classify_class(typ, allocator=allocator, types=types)
elif typ["class"] == "Function":
Expand Down Expand Up @@ -262,7 +269,7 @@ def classify_aggregate(
cur = Eightbyte()
added = False
for f in typ.get("fields", []):
field = types.get(f.get('type'))
field = types.get(f.get("type"))
if not field:
continue
added = False
Expand All @@ -284,12 +291,27 @@ def classify_aggregate(
# tmp.append(classify(f))

if len(eb.fields) > 1:
c1 = classify(eb.fields[0], allocator=allocator, return_classification=True, types=types)
c2 = classify(eb.fields[1], allocator=allocator, return_classification=True, types=types)
c1 = classify(
eb.fields[0],
allocator=allocator,
return_classification=True,
types=types,
)
c2 = classify(
eb.fields[1],
allocator=allocator,
return_classification=True,
types=types,
)
classes.append(merge(c1, c2))
else:
classes.append(
classify(eb.fields[0], allocator=allocator, return_classification=True, types=types)
classify(
eb.fields[0],
allocator=allocator,
return_classification=True,
types=types,
)
)

has_registers = False
Expand All @@ -304,6 +326,23 @@ def classify_aggregate(
return classes


def unwrap_type(typ, types):
"""
Unwrap a type to get to the base type
"""
typename = typ.get("type")
newtype = None

# regular class id or pointer
while typename and len(typename) == 32:
newtype = types[typename]
if "type" in newtype:
typename = newtype["type"]
else:
break
return newtype


def classify_union(typ, allocator, types):
size = typ.get("size", 0)
if size > 64:
Expand All @@ -314,10 +353,14 @@ def classify_union(typ, allocator, types):

# We renamed members to fields
for f in typ.get("fields", []):
field = types.get(f.get('type'))
if not field:

# Unwrap entirely
field = unwrap_type(f, types)
if not field or field.get("type") == "unknown":
continue
c = classify(field, allocator=allocator, return_classification=True, types=types)
c = classify(
field, allocator=allocator, return_classification=True, types=types
)
hi = merge(hi, c.classes[1])
lo = merge(lo, c.classes[0])

Expand All @@ -327,14 +370,36 @@ def classify_union(typ, allocator, types):


def classify_array(typ, allocator, types):
typ = types.get(typ.get('type'))
holder = typ
typ = types.get(typ.get("type"))

# We can't classify this
if "type" not in typ or typ["type"] == "unknown":
return
size = typ.get("size", 0)
if size > 64:
return Classification("Array", [RegisterClass.MEMORY, RegisterClass.NO_CLASS])

typename = typ.get("type")
classname = None

# regular class id or pointer
while len(typename) == 32:
newtype = types[typename]
if "type" in newtype:
typename = newtype["type"]
elif "class" in newtype:
classname = newtype["class"]
break

if not classname:
classname = ClassType.get(typename)

# Just classify the base type
base_type = {"class": ClassType.get(typ.get("type")), "size": size}
return classify(base_type, allocator=allocator, return_classification=True, types=types)
base_type = {"class": classname, "size": size}
return classify(
base_type, allocator=allocator, return_classification=True, types=types
)


def classify_enum(typ):
Expand Down
10 changes: 6 additions & 4 deletions cle/backends/elf/types.py
Original file line number Diff line number Diff line change
Expand Up @@ -17,18 +17,20 @@ class ClassType:
"size_t": "Integer",
"__int128": "Integer",
"bool": "Boolean",
"_Bool": "Boolean",
"char": "Integral",
"float": "Float",
"double": "Float",
"long double": "Float",
}

patterns = {
"int": "Integer",
"char": "Integral",
"float": "Float",
"double": "Float",
"int": "Integer",
"char": "Integral",
"float": "Float",
"double": "Float",
}

@classmethod
def get(cls, typename):
"""
Expand Down
3 changes: 1 addition & 2 deletions examples/allocation/example.cpp
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
// Functions to test register allocation
#include <complex.h>

#include <iostream>
#include <cstdint>

// Integral Types
extern "C" void test_bool(bool x) {}
Expand Down

0 comments on commit e0ac5e6

Please sign in to comment.