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