| #!/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 | |
| } | |
| } | |
| } |