scripts/struct2java.py (55 lines of code) (raw):

#!/usr/bin/env python3 # Copyright (c) Meta Platforms, Inc. and affiliates. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # This script outputs a Java class file giving the offsets of fields # in a C struct. from __future__ import absolute_import from __future__ import division from __future__ import print_function from __future__ import unicode_literals import argparse import sys from elftools.elf.elffile import ELFFile parser = argparse.ArgumentParser(description="Output struct layout") parser.add_argument("elffile", help="ELF file containing debug information") parser.add_argument("struct", help="Name of struct (or typedef of struct)") args = parser.parse_args() def die(fmt, *args): sys.stderr.write(("struct2java.py: " + fmt + "\n") % args) sys.exit(1) def DIE_to_name(DIE): name_attr = DIE.attributes.get("DW_AT_name") if name_attr is not None: return name_attr.value.decode("ascii") return None with open(args.elffile, "rb") as f: elffile = ELFFile(f) if not elffile.has_dwarf_info(): die("file does not contain debug information") dwarfinfo = elffile.get_dwarf_info() structs_by_offset = {} structs_by_name = {} typedefs_by_name = {} for CU in dwarfinfo.iter_CUs(): for DIE in CU.iter_DIEs(): if DIE.tag == "DW_TAG_typedef": name = DIE_to_name(DIE) if name is not None: typedefs_by_name[name] = DIE if DIE.tag == "DW_TAG_structure_type": structs_by_offset[DIE.offset] = DIE name = DIE_to_name(DIE) if name is not None: structs_by_name[name] = DIE struct = structs_by_name.get(args.struct) if struct is None: td = typedefs_by_name.get(args.struct) if td is not None: struct_offset = td.attributes["DW_AT_type"].value + td.cu.cu_offset struct = structs_by_offset.get(struct_offset) if struct is None: die("could not find struct %s", args.struct) print("final class %s {" % args.struct) for child_DIE in struct.iter_children(): if child_DIE.tag == "DW_TAG_member": name = DIE_to_name(child_DIE) offset = child_DIE.attributes["DW_AT_data_member_location"].value print(" public static final int %s = 0x%x;" % (name, offset)) else: die("unknown child of struct DIE: %r", child_DIE) print("}")