#!/bin/gawk # # Copyright (c) 2015 Elvira Khabirova <lineprinter0@gmail.com> # Copyright (c) 2015-2016 Dmitry V. Levin <ldv@altlinux.org> # Copyright (c) 2015-2018 The strace developers. # All rights reserved. # # Redistribution and use in source and binary forms, with or without # modification, are permitted provided that the following conditions # are met: # 1. Redistributions of source code must retain the above copyright # notice, this list of conditions and the following disclaimer. # 2. Redistributions in binary form must reproduce the above copyright # notice, this list of conditions and the following disclaimer in the # documentation and/or other materials provided with the distribution. # 3. The name of the author may not be used to endorse or promote products # derived from this software without specific prior written permission. # # THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR # IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES # OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. # IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, # INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT # NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, # DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY # THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF # THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. function array_get(array_idx, array_member, \ array_return) { array_return = array[array_idx, array_member] if ("" == array_return) { printf("%s: index [%s] without %s\n", FILENAME, array_idx, array_member) > "/dev/stderr" exit 1 } return array_return } function norm_idx(idx) { return sprintf("%016s", idx) } function array_seq(array_idx) { if ((array_idx, "seq") in array) return array[array_idx, "seq"] index_seq++ array[array_idx, "seq"] = index_seq return index_seq } function enter(array_idx, item) { if (array_idx in called) { printf("%s: index loop detected:", FILENAME) > "/dev/stderr" for (item in called) printf(" %s", item) > "/dev/stderr" print "" > "/dev/stderr" exit 1 } called[array_idx] = 1 } function leave(array_idx, to_return) { delete called[array_idx] return to_return } function update_upper_bound(idx, val, \ count) { count = array[idx, "count"] if (count == "") count = 1 array[idx, "count"] = count * val array[idx, "upper_bound"] = array[idx, "upper_bound"] "[" val "]" } function what_is(what_idx, \ item, loc_diff, location, prev_location, prev_returned_size, \ special, to_return, type_idx, enc, i) { enter(what_idx) special = array_get(what_idx, "special") if (special == "base_type") { enc = array_get(what_idx, "encoding") if (enc == 5) { # signed printf("int%s_t ", 8 * array_get(what_idx, "byte_size")) } else if (enc == 7) { # unsigned printf("uint%s_t ", 8 * array_get(what_idx, "byte_size")) } else { # float, signed/unsigned char printf("%s ", array_get(what_idx, "name")) } returned_size = array_get(what_idx, "byte_size") } else if (special == "enumeration_type") { returned_size = array_get(what_idx, "byte_size") printf("uint%s_t ", 8 * returned_size) } else if (special == "pointer_type") { printf("mpers_ptr_t ") returned_size = array_get(what_idx, "byte_size") } else if (special == "array_type") { type_idx = array_get(what_idx, "type") what_is(type_idx) to_return = array[what_idx, "upper_bound"] if ("" == to_return) to_return = "[0]" returned_size = array[what_idx, "count"] * returned_size return leave(what_idx, to_return) } else if (special == "structure_type") { print "struct {" prev_location = 0 location = 0 returned_size = 0 prev_returned_size = 0 for (i = 1; i <= parents_cnt; i += 1) { if (array_parents[aparents_keys[i]] == what_idx) { location = array_get(aparents_keys[i], "location") loc_diff = location - prev_location - \ prev_returned_size if (loc_diff != 0) { printf("unsigned char mpers_%s_%s[%s];\n", "filler", array_seq(aparents_keys[i]), loc_diff) } prev_location = location returned = what_is(aparents_keys[i]) prev_returned_size = returned_size printf("%s%s;\n", array[aparents_keys[i], "name"], returned) } } returned_size = array_get(what_idx, "byte_size") loc_diff = returned_size - prev_location - prev_returned_size if (loc_diff != 0) { printf("unsigned char mpers_%s_%s[%s];\n", "end_filler", array_seq(item), loc_diff) } printf("} ATTRIBUTE_PACKED ") } else if (special == "union_type") { print "union {" for (i = 1; i <= parents_cnt; i += 1) { if (array_parents[aparents_keys[i]] == what_idx) { returned = what_is(aparents_keys[i]) printf("%s%s;\n", array[aparents_keys[i], "name"], returned) } } printf("} ") returned_size = array_get(what_idx, "byte_size") } else if (special == "typedef") { type_idx = array_get(what_idx, "type") return leave(what_idx, what_is(type_idx)) } else if (special == "member") { type_idx = array_get(what_idx, "type") return leave(what_idx, what_is(type_idx)) } else { type_idx = array_get(what_idx, "type") what_is(type_idx) } return leave(what_idx, "") } BEGIN { match(ARCH_FLAG, /[[:digit:]]+/, temparray) default_pointer_size = temparray[0] / 8 print "#include <stdint.h>" } /^<[[:xdigit:]]+>/ { match($0, /([[:alnum:]]+)><([[:alnum:]]+)/, matches) level = matches[1] idx = norm_idx(matches[2]) array[idx, "idx"] = idx parent[level] = idx } /^DW_AT_data_member_location/ { if (!match($0, /\(DW_OP_plus_uconst:[[:space:]]+([[:digit:]]+)\)/, temparray)) match($0, /([[:digit:]]+)/, temparray) array[idx, "location"] = temparray[1] } /^DW_AT_name/ { match($0, /:[[:space:]]+([[:alpha:]_][[:alnum:]_[:space:]]*)/, \ temparray) array_names[idx] = 1 array[idx, "name"] = temparray[1] } /^DW_AT_byte_size/ { match($0, /[[:digit:]]+/, temparray) array[idx, "byte_size"] = temparray[0] } /^DW_AT_encoding/ { match($0, /[[:digit:]]+/, temparray) array[idx, "encoding"] = temparray[0] } /^DW_AT_type/ { match($0, /:[[:space:]]+<0x([[:xdigit:]]*)>$/, temparray) array[idx, "type"] = norm_idx(temparray[1]) } /^DW_AT_upper_bound/ { match($0, /[[:digit:]]+/, temparray) update_upper_bound(parent[level - 1], temparray[0] + 1) } /^DW_AT_count/ { match($0, /[[:digit:]]+/, temparray) update_upper_bound(parent[level - 1], temparray[0]) } /^Abbrev Number:[^(]+\(DW_TAG_/ { if (match($0, /typedef|union_type|structure_type|pointer_type\ |enumeration_type|array_type|base_type|member/, temparray)) { array_special[idx] = temparray[0] array[idx, "special"] = temparray[0] if ("pointer_type" == temparray[0]) array[idx, "byte_size"] = default_pointer_size if (level > 1 && "member" == temparray[0]) array_parents[idx] = parent[level-1] } } END { parents_cnt = asorti(array_parents, aparents_keys) for (item in array_special) { if (array[item, "special"] == "pointer_type") { mpers_ptr_t = \ "uint" 8 * array_get(item, "byte_size") "_t" print "#ifndef mpers_ptr_t_is_" mpers_ptr_t print "typedef " mpers_ptr_t " mpers_ptr_t;" print "#define mpers_ptr_t_is_" mpers_ptr_t print "#endif" break } } for (item in array_names) { if (array[item, "name"] == VAR_NAME) { type = array_get(item, "type") print "typedef" what_is(type) name = array_get(type, "name") print ARCH_FLAG "_" name ";" print "#define MPERS_" \ ARCH_FLAG "_" name " " \ ARCH_FLAG "_" name break } } }