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("}")