1 /* $OpenBSD: aicasm_symbol.c,v 1.6 2002/11/19 18:36:18 jason Exp $ */ 2 /* 3 * Aic7xxx SCSI host adapter firmware asssembler symbol table implementation 4 * 5 * Copyright (c) 1997 Justin T. Gibbs. 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 * without modification. 14 * 2. Redistributions in binary form must reproduce at minimum a disclaimer 15 * substantially similar to the "NO WARRANTY" disclaimer below 16 * ("Disclaimer") and any redistribution must be conditioned upon 17 * including a substantially similar Disclaimer requirement for further 18 * binary redistribution. 19 * 3. Neither the names of the above-listed copyright holders nor the names 20 * of any contributors may be used to endorse or promote products derived 21 * from this software without specific prior written permission. 22 * 23 * Alternatively, this software may be distributed under the terms of the 24 * GNU General Public License ("GPL") version 2 as published by the Free 25 * Software Foundation. 26 * 27 * NO WARRANTY 28 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 29 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 30 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR 31 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 32 * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 33 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 34 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 35 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, 36 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING 37 * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 38 * POSSIBILITY OF SUCH DAMAGES. 39 * 40 * $FreeBSD: src/sys/dev/aic7xxx/aicasm/aicasm_symbol.c,v 1.17 2002/06/06 16:07:18 gibbs Exp $ 41 */ 42 43 #include <sys/types.h> 44 45 #include <db.h> 46 #include <fcntl.h> 47 #include <regex.h> 48 #include <stdio.h> 49 #include <stdlib.h> 50 #include <string.h> 51 #include <sysexits.h> 52 53 #include "aicasm_symbol.h" 54 #include "aicasm.h" 55 56 static DB *symtable; 57 58 symbol_t * 59 symbol_create(name) 60 char *name; 61 { 62 symbol_t *new_symbol; 63 64 new_symbol = (symbol_t *)malloc(sizeof(symbol_t)); 65 if (new_symbol == NULL) { 66 perror("Unable to create new symbol"); 67 exit(EX_SOFTWARE); 68 } 69 memset(new_symbol, 0, sizeof(*new_symbol)); 70 new_symbol->name = strdup(name); 71 new_symbol->type = UNINITIALIZED; 72 return (new_symbol); 73 } 74 75 void 76 symbol_delete(symbol) 77 symbol_t *symbol; 78 { 79 if (symtable != NULL) { 80 DBT key; 81 82 key.data = symbol->name; 83 key.size = strlen(symbol->name); 84 symtable->del(symtable, &key, /*flags*/0); 85 } 86 switch(symbol->type) { 87 case SCBLOC: 88 case SRAMLOC: 89 case REGISTER: 90 if (symbol->info.rinfo != NULL) 91 free(symbol->info.rinfo); 92 break; 93 case ALIAS: 94 if (symbol->info.ainfo != NULL) 95 free(symbol->info.ainfo); 96 break; 97 case MASK: 98 case BIT: 99 if (symbol->info.minfo != NULL) { 100 symlist_free(&symbol->info.minfo->symrefs); 101 free(symbol->info.minfo); 102 } 103 break; 104 case DOWNLOAD_CONST: 105 case CONST: 106 if (symbol->info.cinfo != NULL) 107 free(symbol->info.cinfo); 108 break; 109 case LABEL: 110 if (symbol->info.linfo != NULL) 111 free(symbol->info.linfo); 112 break; 113 case UNINITIALIZED: 114 default: 115 break; 116 } 117 free(symbol->name); 118 free(symbol); 119 } 120 121 void 122 symtable_open() 123 { 124 symtable = dbopen(/*filename*/NULL, 125 O_CREAT | O_NONBLOCK | O_RDWR, /*mode*/0, DB_HASH, 126 /*openinfo*/NULL); 127 128 if (symtable == NULL) { 129 perror("Symbol table creation failed"); 130 exit(EX_SOFTWARE); 131 /* NOTREACHED */ 132 } 133 } 134 135 void 136 symtable_close() 137 { 138 if (symtable != NULL) { 139 DBT key; 140 DBT data; 141 142 while (symtable->seq(symtable, &key, &data, R_FIRST) == 0) { 143 symbol_t *stored_ptr; 144 145 memcpy(&stored_ptr, data.data, sizeof(stored_ptr)); 146 symbol_delete(stored_ptr); 147 } 148 symtable->close(symtable); 149 } 150 } 151 152 /* 153 * The semantics of get is to return an uninitialized symbol entry 154 * if a lookup fails. 155 */ 156 symbol_t * 157 symtable_get(name) 158 char *name; 159 { 160 symbol_t *stored_ptr; 161 DBT key; 162 DBT data; 163 int retval; 164 165 key.data = (void *)name; 166 key.size = strlen(name); 167 168 if ((retval = symtable->get(symtable, &key, &data, /*flags*/0)) != 0) { 169 if (retval == -1) { 170 perror("Symbol table get operation failed"); 171 exit(EX_SOFTWARE); 172 /* NOTREACHED */ 173 } else if (retval == 1) { 174 /* Symbol wasn't found, so create a new one */ 175 symbol_t *new_symbol; 176 177 new_symbol = symbol_create(name); 178 data.data = &new_symbol; 179 data.size = sizeof(new_symbol); 180 if (symtable->put(symtable, &key, &data, 181 /*flags*/0) !=0) { 182 perror("Symtable put failed"); 183 exit(EX_SOFTWARE); 184 } 185 return (new_symbol); 186 } else { 187 perror("Unexpected return value from db get routine"); 188 exit(EX_SOFTWARE); 189 /* NOTREACHED */ 190 } 191 } 192 memcpy(&stored_ptr, data.data, sizeof(stored_ptr)); 193 return (stored_ptr); 194 } 195 196 symbol_node_t * 197 symlist_search(symlist, symname) 198 symlist_t *symlist; 199 char *symname; 200 { 201 symbol_node_t *curnode; 202 203 SLIST_FOREACH(curnode, symlist, links) { 204 if (strcmp(symname, curnode->symbol->name) == 0) 205 break; 206 } 207 return (curnode); 208 } 209 210 void 211 symlist_add(symlist, symbol, how) 212 symlist_t *symlist; 213 symbol_t *symbol; 214 int how; 215 { 216 symbol_node_t *newnode; 217 218 newnode = (symbol_node_t *)malloc(sizeof(symbol_node_t)); 219 if (newnode == NULL) { 220 stop("symlist_add: Unable to malloc symbol_node", EX_SOFTWARE); 221 /* NOTREACHED */ 222 } 223 newnode->symbol = symbol; 224 if (how == SYMLIST_SORT) { 225 symbol_node_t *curnode; 226 int mask; 227 228 mask = FALSE; 229 switch(symbol->type) { 230 case REGISTER: 231 case SCBLOC: 232 case SRAMLOC: 233 break; 234 case BIT: 235 case MASK: 236 mask = TRUE; 237 break; 238 default: 239 stop("symlist_add: Invalid symbol type for sorting", 240 EX_SOFTWARE); 241 /* NOTREACHED */ 242 } 243 244 curnode = SLIST_FIRST(symlist); 245 if (curnode == NULL 246 || (mask && (curnode->symbol->info.minfo->mask > 247 newnode->symbol->info.minfo->mask)) 248 || (!mask && (curnode->symbol->info.rinfo->address > 249 newnode->symbol->info.rinfo->address))) { 250 SLIST_INSERT_HEAD(symlist, newnode, links); 251 return; 252 } 253 254 while (1) { 255 if (SLIST_NEXT(curnode, links) == SLIST_END(symlist)) { 256 SLIST_INSERT_AFTER(curnode, newnode, 257 links); 258 break; 259 } else { 260 symbol_t *cursymbol; 261 262 cursymbol = SLIST_NEXT(curnode, links)->symbol; 263 if ((mask && (cursymbol->info.minfo->mask > 264 symbol->info.minfo->mask)) 265 || (!mask &&(cursymbol->info.rinfo->address > 266 symbol->info.rinfo->address))){ 267 SLIST_INSERT_AFTER(curnode, newnode, 268 links); 269 break; 270 } 271 } 272 curnode = SLIST_NEXT(curnode, links); 273 } 274 } else { 275 SLIST_INSERT_HEAD(symlist, newnode, links); 276 } 277 } 278 279 void 280 symlist_free(symlist) 281 symlist_t *symlist; 282 { 283 symbol_node_t *node; 284 285 while (!SLIST_EMPTY(symlist)) { 286 node = SLIST_FIRST(symlist); 287 SLIST_REMOVE_HEAD(symlist, links); 288 free(node); 289 } 290 } 291 292 void 293 symlist_merge(symlist_dest, symlist_src1, symlist_src2) 294 symlist_t *symlist_dest; 295 symlist_t *symlist_src1; 296 symlist_t *symlist_src2; 297 { 298 symbol_node_t *node; 299 300 *symlist_dest = *symlist_src1; 301 while((node = SLIST_FIRST(symlist_src2)) != NULL) { 302 SLIST_REMOVE_HEAD(symlist_src2, links); 303 SLIST_INSERT_HEAD(symlist_dest, node, links); 304 } 305 306 /* These are now empty */ 307 SLIST_INIT(symlist_src1); 308 SLIST_INIT(symlist_src2); 309 } 310 311 void 312 symtable_dump(ofile) 313 FILE *ofile; 314 { 315 /* 316 * Sort the registers by address with a simple insertion sort. 317 * Put bitmasks next to the first register that defines them. 318 * Put constants at the end. 319 */ 320 symlist_t registers; 321 symlist_t masks; 322 symlist_t constants; 323 symlist_t download_constants; 324 symlist_t aliases; 325 symlist_t exported_labels; 326 u_int i; 327 328 SLIST_INIT(®isters); 329 SLIST_INIT(&masks); 330 SLIST_INIT(&constants); 331 SLIST_INIT(&download_constants); 332 SLIST_INIT(&aliases); 333 SLIST_INIT(&exported_labels); 334 335 if (symtable != NULL) { 336 DBT key; 337 DBT data; 338 int flag = R_FIRST; 339 340 while (symtable->seq(symtable, &key, &data, flag) == 0) { 341 symbol_t *cursym; 342 343 memcpy(&cursym, data.data, sizeof(cursym)); 344 switch(cursym->type) { 345 case REGISTER: 346 case SCBLOC: 347 case SRAMLOC: 348 symlist_add(®isters, cursym, SYMLIST_SORT); 349 break; 350 case MASK: 351 case BIT: 352 symlist_add(&masks, cursym, SYMLIST_SORT); 353 break; 354 case CONST: 355 symlist_add(&constants, cursym, 356 SYMLIST_INSERT_HEAD); 357 break; 358 case DOWNLOAD_CONST: 359 symlist_add(&download_constants, cursym, 360 SYMLIST_INSERT_HEAD); 361 break; 362 case ALIAS: 363 symlist_add(&aliases, cursym, 364 SYMLIST_INSERT_HEAD); 365 break; 366 case LABEL: 367 if (cursym->info.linfo->exported == 0) 368 break; 369 symlist_add(&exported_labels, cursym, 370 SYMLIST_INSERT_HEAD); 371 break; 372 default: 373 break; 374 } 375 flag = R_NEXT; 376 } 377 378 /* Put in the masks and bits */ 379 while (SLIST_FIRST(&masks) != SLIST_END(&masks)) { 380 symbol_node_t *curnode; 381 symbol_node_t *regnode; 382 char *regname; 383 384 curnode = SLIST_FIRST(&masks); 385 SLIST_REMOVE_HEAD(&masks, links); 386 387 regnode = 388 SLIST_FIRST(&curnode->symbol->info.minfo->symrefs); 389 regname = regnode->symbol->name; 390 regnode = symlist_search(®isters, regname); 391 SLIST_INSERT_AFTER(regnode, curnode, links); 392 } 393 394 /* Add the aliases */ 395 while (SLIST_FIRST(&aliases) != SLIST_END(&aliases)) { 396 symbol_node_t *curnode; 397 symbol_node_t *regnode; 398 char *regname; 399 400 curnode = SLIST_FIRST(&aliases); 401 SLIST_REMOVE_HEAD(&aliases, links); 402 403 regname = curnode->symbol->info.ainfo->parent->name; 404 regnode = symlist_search(®isters, regname); 405 SLIST_INSERT_AFTER(regnode, curnode, links); 406 } 407 408 /* Output what we have */ 409 fprintf(ofile, 410 "/*\n" 411 " * DO NOT EDIT - This file is automatically generated\n" 412 " * from the following source files:\n" 413 " *\n" 414 "%s */\n", versions); 415 while (SLIST_FIRST(®isters) != SLIST_END(®isters)) { 416 symbol_node_t *curnode; 417 u_int value; 418 char *tab_str; 419 char *tab_str2; 420 421 curnode = SLIST_FIRST(®isters); 422 SLIST_REMOVE_HEAD(®isters, links); 423 switch(curnode->symbol->type) { 424 case REGISTER: 425 case SCBLOC: 426 case SRAMLOC: 427 fprintf(ofile, "\n"); 428 value = curnode->symbol->info.rinfo->address; 429 tab_str = "\t"; 430 tab_str2 = "\t\t"; 431 break; 432 case ALIAS: 433 { 434 symbol_t *parent; 435 436 parent = curnode->symbol->info.ainfo->parent; 437 value = parent->info.rinfo->address; 438 tab_str = "\t"; 439 tab_str2 = "\t\t"; 440 break; 441 } 442 case MASK: 443 case BIT: 444 value = curnode->symbol->info.minfo->mask; 445 tab_str = "\t\t"; 446 tab_str2 = "\t"; 447 break; 448 default: 449 value = 0; /* Quiet compiler */ 450 tab_str = NULL; 451 tab_str2 = NULL; 452 stop("symtable_dump: Invalid symbol type " 453 "encountered", EX_SOFTWARE); 454 break; 455 } 456 fprintf(ofile, "#define%s%-16s%s0x%02x\n", 457 tab_str, curnode->symbol->name, tab_str2, 458 value); 459 free(curnode); 460 } 461 fprintf(ofile, "\n\n"); 462 463 while (SLIST_FIRST(&constants) != SLIST_END(&constants)) { 464 symbol_node_t *curnode; 465 466 curnode = SLIST_FIRST(&constants); 467 SLIST_REMOVE_HEAD(&constants, links); 468 fprintf(ofile, "#define\t%-8s\t0x%02x\n", 469 curnode->symbol->name, 470 curnode->symbol->info.cinfo->value); 471 free(curnode); 472 } 473 474 475 fprintf(ofile, "\n\n/* Downloaded Constant Definitions */\n"); 476 477 while (SLIST_FIRST(&download_constants) != 478 SLIST_END(&download_constants)) { 479 symbol_node_t *curnode; 480 481 curnode = SLIST_FIRST(&download_constants); 482 SLIST_REMOVE_HEAD(&download_constants, links); 483 fprintf(ofile, "#define\t%-8s\t0x%02x\n", 484 curnode->symbol->name, 485 curnode->symbol->info.cinfo->value); 486 free(curnode); 487 } 488 fprintf(ofile, "#define\tDOWNLOAD_CONST_COUNT\t0x%02x\n", i); 489 490 fprintf(ofile, "\n\n/* Exported Labels */\n"); 491 492 while (SLIST_FIRST(&exported_labels) != 493 SLIST_END(&exported_labels)) { 494 symbol_node_t *curnode; 495 496 curnode = SLIST_FIRST(&exported_labels); 497 SLIST_REMOVE_HEAD(&exported_labels, links); 498 fprintf(ofile, "#define\tLABEL_%-8s\t0x%02x\n", 499 curnode->symbol->name, 500 curnode->symbol->info.linfo->address); 501 free(curnode); 502 } 503 } 504 } 505 506