1#!/bin/gawk 2# 3# Copyright (c) 2015 Elvira Khabirova <lineprinter0@gmail.com> 4# Copyright (c) 2015-2016 Dmitry V. Levin <ldv@altlinux.org> 5# Copyright (c) 2015-2018 The strace developers. 6# All rights reserved. 7# 8# Redistribution and use in source and binary forms, with or without 9# modification, are permitted provided that the following conditions 10# are met: 11# 1. Redistributions of source code must retain the above copyright 12# notice, this list of conditions and the following disclaimer. 13# 2. Redistributions in binary form must reproduce the above copyright 14# notice, this list of conditions and the following disclaimer in the 15# documentation and/or other materials provided with the distribution. 16# 3. The name of the author may not be used to endorse or promote products 17# derived from this software without specific prior written permission. 18# 19# THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 20# IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 21# OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 22# IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 23# INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 24# NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 25# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 26# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 27# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 28# THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 29 30function array_get(array_idx, array_member, \ 31 array_return) 32{ 33 array_return = array[array_idx, array_member] 34 if ("" == array_return) { 35 printf("%s: index [%s] without %s\n", 36 FILENAME, array_idx, array_member) > "/dev/stderr" 37 exit 1 38 } 39 return array_return 40} 41function norm_idx(idx) 42{ 43 return sprintf("%016s", idx) 44} 45function array_seq(array_idx) 46{ 47 if ((array_idx, "seq") in array) 48 return array[array_idx, "seq"] 49 index_seq++ 50 array[array_idx, "seq"] = index_seq 51 return index_seq 52} 53function enter(array_idx, 54 item) 55{ 56 if (array_idx in called) { 57 printf("%s: index loop detected:", FILENAME) > "/dev/stderr" 58 for (item in called) 59 printf(" %s", item) > "/dev/stderr" 60 print "" > "/dev/stderr" 61 exit 1 62 } 63 called[array_idx] = 1 64} 65function leave(array_idx, to_return) 66{ 67 delete called[array_idx] 68 return to_return 69} 70function update_upper_bound(idx, val, \ 71 count) 72{ 73 count = array[idx, "count"] 74 if (count == "") 75 count = 1 76 array[idx, "count"] = count * val 77 array[idx, "upper_bound"] = array[idx, "upper_bound"] "[" val "]" 78} 79function what_is(what_idx, \ 80 item, loc_diff, location, prev_location, prev_returned_size, \ 81 special, to_return, type_idx, enc, i) 82{ 83 enter(what_idx) 84 special = array_get(what_idx, "special") 85 if (special == "base_type") { 86 enc = array_get(what_idx, "encoding") 87 if (enc == 5) { # signed 88 printf("int%s_t ", 89 8 * array_get(what_idx, "byte_size")) 90 } else if (enc == 7) { # unsigned 91 printf("uint%s_t ", 92 8 * array_get(what_idx, "byte_size")) 93 } else { # float, signed/unsigned char 94 printf("%s ", array_get(what_idx, "name")) 95 } 96 returned_size = array_get(what_idx, "byte_size") 97 } else if (special == "enumeration_type") { 98 returned_size = array_get(what_idx, "byte_size") 99 printf("uint%s_t ", 8 * returned_size) 100 } else if (special == "pointer_type") { 101 printf("mpers_ptr_t ") 102 returned_size = array_get(what_idx, "byte_size") 103 } else if (special == "array_type") { 104 type_idx = array_get(what_idx, "type") 105 what_is(type_idx) 106 to_return = array[what_idx, "upper_bound"] 107 if ("" == to_return) 108 to_return = "[0]" 109 returned_size = array[what_idx, "count"] * returned_size 110 return leave(what_idx, to_return) 111 } else if (special == "structure_type") { 112 print "struct {" 113 prev_location = 0 114 location = 0 115 returned_size = 0 116 prev_returned_size = 0 117 for (i = 1; i <= parents_cnt; i += 1) { 118 if (array_parents[aparents_keys[i]] == what_idx) { 119 location = array_get(aparents_keys[i], "location") 120 loc_diff = location - prev_location - \ 121 prev_returned_size 122 if (loc_diff != 0) { 123 printf("unsigned char mpers_%s_%s[%s];\n", 124 "filler", array_seq(aparents_keys[i]), loc_diff) 125 } 126 prev_location = location 127 returned = what_is(aparents_keys[i]) 128 prev_returned_size = returned_size 129 printf("%s%s;\n", array[aparents_keys[i], "name"], returned) 130 } 131 } 132 returned_size = array_get(what_idx, "byte_size") 133 loc_diff = returned_size - prev_location - prev_returned_size 134 if (loc_diff != 0) { 135 printf("unsigned char mpers_%s_%s[%s];\n", 136 "end_filler", array_seq(item), loc_diff) 137 } 138 printf("} ATTRIBUTE_PACKED ") 139 } else if (special == "union_type") { 140 print "union {" 141 for (i = 1; i <= parents_cnt; i += 1) { 142 if (array_parents[aparents_keys[i]] == what_idx) { 143 returned = what_is(aparents_keys[i]) 144 printf("%s%s;\n", array[aparents_keys[i], "name"], returned) 145 } 146 } 147 printf("} ") 148 returned_size = array_get(what_idx, "byte_size") 149 } else if (special == "typedef") { 150 type_idx = array_get(what_idx, "type") 151 return leave(what_idx, what_is(type_idx)) 152 } else if (special == "member") { 153 type_idx = array_get(what_idx, "type") 154 return leave(what_idx, what_is(type_idx)) 155 } else { 156 type_idx = array_get(what_idx, "type") 157 what_is(type_idx) 158 } 159 return leave(what_idx, "") 160} 161BEGIN { 162 match(ARCH_FLAG, /[[:digit:]]+/, temparray) 163 default_pointer_size = temparray[0] / 8 164 print "#include <stdint.h>" 165} 166/^<[[:xdigit:]]+>/ { 167 match($0, /([[:alnum:]]+)><([[:alnum:]]+)/, matches) 168 level = matches[1] 169 idx = norm_idx(matches[2]) 170 array[idx, "idx"] = idx 171 parent[level] = idx 172} 173/^DW_AT_data_member_location/ { 174 if (!match($0, /\(DW_OP_plus_uconst:[[:space:]]+([[:digit:]]+)\)/, temparray)) 175 match($0, /([[:digit:]]+)/, temparray) 176 array[idx, "location"] = temparray[1] 177} 178/^DW_AT_name/ { 179 match($0, /:[[:space:]]+([[:alpha:]_][[:alnum:]_[:space:]]*)/, \ 180 temparray) 181 array_names[idx] = 1 182 array[idx, "name"] = temparray[1] 183} 184/^DW_AT_byte_size/ { 185 match($0, /[[:digit:]]+/, temparray) 186 array[idx, "byte_size"] = temparray[0] 187} 188/^DW_AT_encoding/ { 189 match($0, /[[:digit:]]+/, temparray) 190 array[idx, "encoding"] = temparray[0] 191} 192/^DW_AT_type/ { 193 match($0, /:[[:space:]]+<0x([[:xdigit:]]*)>$/, temparray) 194 array[idx, "type"] = norm_idx(temparray[1]) 195} 196/^DW_AT_upper_bound/ { 197 match($0, /[[:digit:]]+/, temparray) 198 update_upper_bound(parent[level - 1], temparray[0] + 1) 199} 200/^DW_AT_count/ { 201 match($0, /[[:digit:]]+/, temparray) 202 update_upper_bound(parent[level - 1], temparray[0]) 203} 204/^Abbrev Number:[^(]+\(DW_TAG_/ { 205 if (match($0, /typedef|union_type|structure_type|pointer_type\ 206|enumeration_type|array_type|base_type|member/, temparray)) { 207 array_special[idx] = temparray[0] 208 array[idx, "special"] = temparray[0] 209 if ("pointer_type" == temparray[0]) 210 array[idx, "byte_size"] = default_pointer_size 211 if (level > 1 && "member" == temparray[0]) 212 array_parents[idx] = parent[level-1] 213 } 214} 215END { 216 parents_cnt = asorti(array_parents, aparents_keys) 217 218 for (item in array_special) { 219 if (array[item, "special"] == "pointer_type") { 220 mpers_ptr_t = \ 221 "uint" 8 * array_get(item, "byte_size") "_t" 222 print "#ifndef mpers_ptr_t_is_" mpers_ptr_t 223 print "typedef " mpers_ptr_t " mpers_ptr_t;" 224 print "#define mpers_ptr_t_is_" mpers_ptr_t 225 print "#endif" 226 break 227 } 228 } 229 for (item in array_names) { 230 if (array[item, "name"] == VAR_NAME) { 231 type = array_get(item, "type") 232 print "typedef" 233 what_is(type) 234 name = array_get(type, "name") 235 print ARCH_FLAG "_" name ";" 236 print "#define MPERS_" \ 237 ARCH_FLAG "_" name " " \ 238 ARCH_FLAG "_" name 239 break 240 } 241 } 242} 243