#!/bin/gawk # # Copyright (c) 2015 Elvira Khabirova # Copyright (c) 2015 Dmitry V. Levin # 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 compare_indices(i1, v1, i2, v2) { c1 = strtonum(sprintf("%s", i1)) c2 = strtonum(sprintf("%s", i2)) if (c1 < c2) return -1 return (c1 != c2) } 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 array_seq(array_idx) { if ("seq" in array[array_idx]) return array[array_idx]["seq"] index_seq++ array[array_idx]["seq"] = index_seq return index_seq } function enter(array_idx) { 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 what_is(what_idx, type_idx, special, item, \ location, prev_location, prev_returned_size) { enter(what_idx) special = array_get(what_idx, "special") switch (special) { case "base_type": switch (array_get(what_idx, "encoding")) { case 5: # signed printf("int%s_t ", 8 * array_get(what_idx, "byte_size")) break case 7: # unsigned printf("uint%s_t ", 8 * array_get(what_idx, "byte_size")) break default: # float, signed/unsigned char printf("%s ", array_get(what_idx, "name")) break } returned_size = array_get(what_idx, "byte_size") break case "enumeration_type": type_idx = array_get(what_idx, "type") returned_size = array_get(what_idx, "byte_size") printf("uint%s_t ", 8 * returned_size) break case "pointer_type": printf("mpers_ptr_t ") returned_size = array_get(what_idx, "byte_size") break case "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 = to_return * returned_size return leave(what_idx, to_return) break case "structure_type": print "struct {" prev_location = 0 location = 0 returned_size = 0 prev_returned_size = 0 for (item in array) { if ("parent" in array[item] && \ array_get(item, "parent") == what_idx) { location = array_get(item, "location") loc_diff = location - prev_location - \ prev_returned_size if (loc_diff != 0) { printf("unsigned char mpers_%s_%s[%s];\n", "filler", array_seq(item), loc_diff) } prev_location = location returned = what_is(item) prev_returned_size = returned_size printf("%s", array[item]["name"]) if ("" != returned) { printf("[%s]", returned) } print ";" } } 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 ") break case "union_type": print "union {" for (item in array) { if ("parent" in array[item] && \ array_get(item, "parent") == what_idx) { returned = what_is(item) printf("%s", array_get(item, "name")) if ("" != returned) { printf("[%s]", returned) } print ";" } } printf("} ") returned_size = array_get(what_idx, "byte_size") break case "typedef": type_idx = array_get(what_idx, "type") return leave(what_idx, what_is(type_idx)) break case "member": type_idx = array_get(what_idx, "type") return leave(what_idx, what_is(type_idx)) break default: type_idx = array_get(what_idx, "type") what_is(type_idx) break } return leave(what_idx, "") } BEGIN { print "#include " } /^<[[:xdigit:]]+>/ { match($0, /([[:alnum:]]+)><([[:alnum:]]+)/, matches) level = matches[1] idx = "0x" matches[2] array[idx]["idx"] = idx parent[level] = idx if (level > 1) { array[idx]["parent"] = parent[level-1] } } /^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[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"] = temparray[1] } /^DW_AT_upper_bound/ { match($0, /[[:digit:]]+/, temparray) array[parent[level-1]]["upper_bound"] = temparray[0] + 1 } /^Abbrev Number:[^(]+\(DW_TAG_/ { if (match($0, /typedef|union_type|structure_type|pointer_type\ |enumeration_type|array_type|base_type|member/, temparray)) { array[idx]["special"] = temparray[0] } } END { PROCINFO["sorted_in"] = "compare_indices" for (item in array) { if (array[item]["special"] == "pointer_type") { print "typedef uint" \ 8 * array_get(item, "byte_size") "_t mpers_ptr_t;" break } } for (item in array) { 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 } } }