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