Rob Pike | 0cafb9e | 2008-06-04 14:37:38 -0700 | [diff] [blame] | 1 | // Inferno utils/6l/obj.c |
| 2 | // http://code.google.com/p/inferno-os/source/browse/utils/6l/obj.c |
| 3 | // |
| 4 | // Copyright © 1994-1999 Lucent Technologies Inc. All rights reserved. |
| 5 | // Portions Copyright © 1995-1997 C H Forsyth (forsyth@terzarima.net) |
| 6 | // Portions Copyright © 1997-1999 Vita Nuova Limited |
| 7 | // Portions Copyright © 2000-2007 Vita Nuova Holdings Limited (www.vitanuova.com) |
| 8 | // Portions Copyright © 2004,2006 Bruce Ellis |
| 9 | // Portions Copyright © 2005-2007 C H Forsyth (forsyth@terzarima.net) |
| 10 | // Revisions Copyright © 2000-2007 Lucent Technologies Inc. and others |
| 11 | // Portions Copyright © 2009 The Go Authors. All rights reserved. |
| 12 | // |
| 13 | // Permission is hereby granted, free of charge, to any person obtaining a copy |
| 14 | // of this software and associated documentation files (the "Software"), to deal |
| 15 | // in the Software without restriction, including without limitation the rights |
| 16 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell |
| 17 | // copies of the Software, and to permit persons to whom the Software is |
| 18 | // furnished to do so, subject to the following conditions: |
| 19 | // |
| 20 | // The above copyright notice and this permission notice shall be included in |
| 21 | // all copies or substantial portions of the Software. |
| 22 | // |
| 23 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR |
| 24 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, |
| 25 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE |
| 26 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER |
| 27 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, |
| 28 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN |
| 29 | // THE SOFTWARE. |
| 30 | |
Russ Cox | 085be17 | 2010-10-13 15:51:21 -0400 | [diff] [blame] | 31 | // Reading object files. |
| 32 | |
Rob Pike | 0cafb9e | 2008-06-04 14:37:38 -0700 | [diff] [blame] | 33 | #define EXTERN |
| 34 | #include "l.h" |
Russ Cox | c287497 | 2009-10-07 00:11:59 -0700 | [diff] [blame] | 35 | #include "../ld/lib.h" |
Russ Cox | 0e25c1d | 2009-08-21 13:08:11 -0700 | [diff] [blame] | 36 | #include "../ld/elf.h" |
Russ Cox | 2157025 | 2009-09-30 17:33:39 -0700 | [diff] [blame] | 37 | #include "../ld/macho.h" |
Luuk van Dijk | ca9098e | 2010-08-18 16:53:22 +0200 | [diff] [blame] | 38 | #include "../ld/dwarf.h" |
Wei Guangjing | 3aec551 | 2011-01-20 09:21:10 -0500 | [diff] [blame] | 39 | #include "../ld/pe.h" |
Rob Pike | 0cafb9e | 2008-06-04 14:37:38 -0700 | [diff] [blame] | 40 | #include <ar.h> |
| 41 | |
Rob Pike | 0cafb9e | 2008-06-04 14:37:38 -0700 | [diff] [blame] | 42 | char *noname = "<none>"; |
Rob Pike | 0cafb9e | 2008-06-04 14:37:38 -0700 | [diff] [blame] | 43 | char thechar = '6'; |
Ken Thompson | e2c3ec3 | 2008-06-05 16:56:23 -0700 | [diff] [blame] | 44 | char* thestring = "amd64"; |
| 45 | char* paramspace = "FP"; |
Rob Pike | 0cafb9e | 2008-06-04 14:37:38 -0700 | [diff] [blame] | 46 | |
| 47 | /* |
| 48 | * -H2 -T4136 -R4096 is plan9 64-bit format |
| 49 | * -H3 -T4128 -R4096 is plan9 32-bit format |
| 50 | * -H5 -T0x80110000 -R4096 is ELF32 |
| 51 | * -H6 -Tx -Rx is apple MH-exec |
Rob Pike | 073486c | 2008-06-15 17:22:57 -0700 | [diff] [blame] | 52 | * -H7 -Tx -Rx is linux elf-exec |
Devon H. O'Dell | 0489a26 | 2009-11-17 08:20:58 -0800 | [diff] [blame] | 53 | * -H9 -Tx -Rx is FreeBSD elf-exec |
Rob Pike | 0cafb9e | 2008-06-04 14:37:38 -0700 | [diff] [blame] | 54 | * |
| 55 | * options used: 189BLQSWabcjlnpsvz |
| 56 | */ |
| 57 | |
Rob Pike | 0cafb9e | 2008-06-04 14:37:38 -0700 | [diff] [blame] | 58 | void |
Russ Cox | 48974f5 | 2009-04-30 13:32:39 -0700 | [diff] [blame] | 59 | usage(void) |
| 60 | { |
Ian Lance Taylor | 9040da9 | 2011-02-01 12:49:56 -0800 | [diff] [blame] | 61 | fprint(2, "usage: 6l [-options] [-E entry] [-H head] [-I interpreter] [-L dir] [-T text] [-R rnd] [-r path] [-o out] main.6\n"); |
Russ Cox | 48974f5 | 2009-04-30 13:32:39 -0700 | [diff] [blame] | 62 | exits("usage"); |
| 63 | } |
| 64 | |
| 65 | void |
Rob Pike | 0cafb9e | 2008-06-04 14:37:38 -0700 | [diff] [blame] | 66 | main(int argc, char *argv[]) |
| 67 | { |
Russ Cox | 085be17 | 2010-10-13 15:51:21 -0400 | [diff] [blame] | 68 | int c; |
Rob Pike | 0cafb9e | 2008-06-04 14:37:38 -0700 | [diff] [blame] | 69 | |
| 70 | Binit(&bso, 1, OWRITE); |
| 71 | cout = -1; |
| 72 | listinit(); |
| 73 | memset(debug, 0, sizeof(debug)); |
| 74 | nerrors = 0; |
| 75 | outfile = "6.out"; |
| 76 | HEADTYPE = -1; |
| 77 | INITTEXT = -1; |
| 78 | INITDAT = -1; |
| 79 | INITRND = -1; |
| 80 | INITENTRY = 0; |
Ken Thompson | e2c3ec3 | 2008-06-05 16:56:23 -0700 | [diff] [blame] | 81 | |
Rob Pike | 0cafb9e | 2008-06-04 14:37:38 -0700 | [diff] [blame] | 82 | ARGBEGIN { |
| 83 | default: |
| 84 | c = ARGC(); |
Kai Backman | 2f1a321 | 2010-02-03 22:31:38 -0800 | [diff] [blame] | 85 | if(c == 'l') |
| 86 | usage(); |
| 87 | if(c >= 0 && c < sizeof(debug)) |
Rob Pike | 0cafb9e | 2008-06-04 14:37:38 -0700 | [diff] [blame] | 88 | debug[c]++; |
| 89 | break; |
| 90 | case 'o': /* output to (next arg) */ |
Russ Cox | 48974f5 | 2009-04-30 13:32:39 -0700 | [diff] [blame] | 91 | outfile = EARGF(usage()); |
Rob Pike | 0cafb9e | 2008-06-04 14:37:38 -0700 | [diff] [blame] | 92 | break; |
| 93 | case 'E': |
Russ Cox | 48974f5 | 2009-04-30 13:32:39 -0700 | [diff] [blame] | 94 | INITENTRY = EARGF(usage()); |
Rob Pike | 0cafb9e | 2008-06-04 14:37:38 -0700 | [diff] [blame] | 95 | break; |
| 96 | case 'H': |
Russ Cox | 48974f5 | 2009-04-30 13:32:39 -0700 | [diff] [blame] | 97 | HEADTYPE = atolwhex(EARGF(usage())); |
| 98 | break; |
Ian Lance Taylor | 9040da9 | 2011-02-01 12:49:56 -0800 | [diff] [blame] | 99 | case 'I': |
| 100 | interpreter = EARGF(usage()); |
| 101 | break; |
Russ Cox | 48974f5 | 2009-04-30 13:32:39 -0700 | [diff] [blame] | 102 | case 'L': |
Russ Cox | c287497 | 2009-10-07 00:11:59 -0700 | [diff] [blame] | 103 | Lflag(EARGF(usage())); |
Rob Pike | 0cafb9e | 2008-06-04 14:37:38 -0700 | [diff] [blame] | 104 | break; |
| 105 | case 'T': |
Russ Cox | 48974f5 | 2009-04-30 13:32:39 -0700 | [diff] [blame] | 106 | INITTEXT = atolwhex(EARGF(usage())); |
Rob Pike | 0cafb9e | 2008-06-04 14:37:38 -0700 | [diff] [blame] | 107 | break; |
| 108 | case 'D': |
Russ Cox | 48974f5 | 2009-04-30 13:32:39 -0700 | [diff] [blame] | 109 | INITDAT = atolwhex(EARGF(usage())); |
Rob Pike | 0cafb9e | 2008-06-04 14:37:38 -0700 | [diff] [blame] | 110 | break; |
| 111 | case 'R': |
Russ Cox | 48974f5 | 2009-04-30 13:32:39 -0700 | [diff] [blame] | 112 | INITRND = atolwhex(EARGF(usage())); |
Rob Pike | 0cafb9e | 2008-06-04 14:37:38 -0700 | [diff] [blame] | 113 | break; |
Ian Lance Taylor | e6443f6 | 2010-02-26 14:03:52 -0800 | [diff] [blame] | 114 | case 'r': |
| 115 | rpath = EARGF(usage()); |
| 116 | break; |
Andrew Gerrand | b4fb00b | 2010-02-08 09:46:53 -0800 | [diff] [blame] | 117 | case 'V': |
| 118 | print("%cl version %s\n", thechar, getgoversion()); |
| 119 | errorexit(); |
Rob Pike | 0cafb9e | 2008-06-04 14:37:38 -0700 | [diff] [blame] | 120 | } ARGEND |
Russ Cox | 3b1a035 | 2010-01-25 17:53:43 -0800 | [diff] [blame] | 121 | |
| 122 | if(argc != 1) |
Russ Cox | 07393f8 | 2009-06-02 22:33:21 -0700 | [diff] [blame] | 123 | usage(); |
Ken Thompson | e2c3ec3 | 2008-06-05 16:56:23 -0700 | [diff] [blame] | 124 | |
Russ Cox | c287497 | 2009-10-07 00:11:59 -0700 | [diff] [blame] | 125 | libinit(); |
Russ Cox | 489494c | 2010-06-30 23:31:27 -0700 | [diff] [blame] | 126 | if(rpath == nil) |
| 127 | rpath = smprint("%s/pkg/%s_%s", goroot, goos, goarch); |
Rob Pike | e6bc5bf | 2009-10-05 21:31:50 -0700 | [diff] [blame] | 128 | |
Rob Pike | 0cafb9e | 2008-06-04 14:37:38 -0700 | [diff] [blame] | 129 | if(HEADTYPE == -1) { |
Ken Thompson | e2c3ec3 | 2008-06-05 16:56:23 -0700 | [diff] [blame] | 130 | HEADTYPE = 2; |
| 131 | if(strcmp(goos, "linux") == 0) |
| 132 | HEADTYPE = 7; |
| 133 | else |
| 134 | if(strcmp(goos, "darwin") == 0) |
| 135 | HEADTYPE = 6; |
| 136 | else |
Devon H. O'Dell | 60b1a17 | 2009-11-18 16:51:59 -0800 | [diff] [blame] | 137 | if(strcmp(goos, "freebsd") == 0) |
Devon H. O'Dell | 0489a26 | 2009-11-17 08:20:58 -0800 | [diff] [blame] | 138 | HEADTYPE = 9; |
Devon H. O'Dell | 60b1a17 | 2009-11-18 16:51:59 -0800 | [diff] [blame] | 139 | else |
Wei Guangjing | 3aec551 | 2011-01-20 09:21:10 -0500 | [diff] [blame] | 140 | if(strcmp(goos, "windows") == 0) |
| 141 | HEADTYPE = 10; |
| 142 | else |
Ken Thompson | e2c3ec3 | 2008-06-05 16:56:23 -0700 | [diff] [blame] | 143 | print("goos is not known: %s\n", goos); |
Rob Pike | 0cafb9e | 2008-06-04 14:37:38 -0700 | [diff] [blame] | 144 | } |
Ken Thompson | e2c3ec3 | 2008-06-05 16:56:23 -0700 | [diff] [blame] | 145 | |
Rob Pike | 0cafb9e | 2008-06-04 14:37:38 -0700 | [diff] [blame] | 146 | switch(HEADTYPE) { |
| 147 | default: |
| 148 | diag("unknown -H option"); |
| 149 | errorexit(); |
| 150 | case 2: /* plan 9 */ |
| 151 | HEADR = 32L+8L; |
| 152 | if(INITTEXT == -1) |
| 153 | INITTEXT = 4096+HEADR; |
| 154 | if(INITDAT == -1) |
| 155 | INITDAT = 0; |
| 156 | if(INITRND == -1) |
| 157 | INITRND = 4096; |
| 158 | break; |
| 159 | case 3: /* plan 9 */ |
| 160 | HEADR = 32L; |
| 161 | if(INITTEXT == -1) |
| 162 | INITTEXT = 4096+32; |
| 163 | if(INITDAT == -1) |
| 164 | INITDAT = 0; |
| 165 | if(INITRND == -1) |
| 166 | INITRND = 4096; |
| 167 | break; |
| 168 | case 5: /* elf32 executable */ |
| 169 | HEADR = rnd(52L+3*32L, 16); |
| 170 | if(INITTEXT == -1) |
| 171 | INITTEXT = 0x80110000L; |
| 172 | if(INITDAT == -1) |
| 173 | INITDAT = 0; |
| 174 | if(INITRND == -1) |
| 175 | INITRND = 4096; |
| 176 | break; |
| 177 | case 6: /* apple MACH */ |
Russ Cox | e473f42 | 2010-08-04 17:50:22 -0700 | [diff] [blame] | 178 | /* |
| 179 | * OS X system constant - offset from 0(GS) to our TLS. |
| 180 | * Explained in ../../libcgo/darwin_amd64.c. |
| 181 | */ |
| 182 | tlsoffset = 0x8a0; |
Russ Cox | 2157025 | 2009-09-30 17:33:39 -0700 | [diff] [blame] | 183 | machoinit(); |
| 184 | HEADR = MACHORESERVE; |
Russ Cox | 133a158 | 2009-10-03 10:37:12 -0700 | [diff] [blame] | 185 | if(INITRND == -1) |
| 186 | INITRND = 4096; |
Rob Pike | 0cafb9e | 2008-06-04 14:37:38 -0700 | [diff] [blame] | 187 | if(INITTEXT == -1) |
| 188 | INITTEXT = 4096+HEADR; |
| 189 | if(INITDAT == -1) |
| 190 | INITDAT = 0; |
Rob Pike | 0cafb9e | 2008-06-04 14:37:38 -0700 | [diff] [blame] | 191 | break; |
Ken Thompson | e2c3ec3 | 2008-06-05 16:56:23 -0700 | [diff] [blame] | 192 | case 7: /* elf64 executable */ |
Devon H. O'Dell | 0489a26 | 2009-11-17 08:20:58 -0800 | [diff] [blame] | 193 | case 9: /* freebsd */ |
Russ Cox | e473f42 | 2010-08-04 17:50:22 -0700 | [diff] [blame] | 194 | /* |
| 195 | * ELF uses TLS offset negative from FS. |
| 196 | * Translate 0(FS) and 8(FS) into -16(FS) and -8(FS). |
| 197 | * Also known to ../../pkg/runtime/linux/amd64/sys.s |
| 198 | * and ../../libcgo/linux_amd64.s. |
| 199 | */ |
| 200 | tlsoffset = -16; |
Russ Cox | 0e25c1d | 2009-08-21 13:08:11 -0700 | [diff] [blame] | 201 | elfinit(); |
| 202 | HEADR = ELFRESERVE; |
Ken Thompson | e2c3ec3 | 2008-06-05 16:56:23 -0700 | [diff] [blame] | 203 | if(INITTEXT == -1) |
Russ Cox | c3ca056 | 2008-09-08 15:22:55 -0700 | [diff] [blame] | 204 | INITTEXT = (1<<22)+HEADR; |
Ken Thompson | e2c3ec3 | 2008-06-05 16:56:23 -0700 | [diff] [blame] | 205 | if(INITDAT == -1) |
| 206 | INITDAT = 0; |
| 207 | if(INITRND == -1) |
| 208 | INITRND = 4096; |
| 209 | break; |
Wei Guangjing | 3aec551 | 2011-01-20 09:21:10 -0500 | [diff] [blame] | 210 | case 10: /* PE executable */ |
| 211 | peinit(); |
| 212 | HEADR = PEFILEHEADR; |
| 213 | if(INITTEXT == -1) |
| 214 | INITTEXT = PEBASE+PESECTHEADR; |
| 215 | if(INITDAT == -1) |
| 216 | INITDAT = 0; |
| 217 | if(INITRND == -1) |
| 218 | INITRND = PESECTALIGN; |
| 219 | break; |
Rob Pike | 0cafb9e | 2008-06-04 14:37:38 -0700 | [diff] [blame] | 220 | } |
| 221 | if(INITDAT != 0 && INITRND != 0) |
Russ Cox | d9c989f | 2010-10-13 16:20:22 -0400 | [diff] [blame] | 222 | print("warning: -D0x%llux is ignored because of -R0x%ux\n", |
Rob Pike | 0cafb9e | 2008-06-04 14:37:38 -0700 | [diff] [blame] | 223 | INITDAT, INITRND); |
| 224 | if(debug['v']) |
Russ Cox | d9c989f | 2010-10-13 16:20:22 -0400 | [diff] [blame] | 225 | Bprint(&bso, "HEADER = -H%d -T0x%llux -D0x%llux -R0x%ux\n", |
Rob Pike | 0cafb9e | 2008-06-04 14:37:38 -0700 | [diff] [blame] | 226 | HEADTYPE, INITTEXT, INITDAT, INITRND); |
| 227 | Bflush(&bso); |
Russ Cox | 085be17 | 2010-10-13 15:51:21 -0400 | [diff] [blame] | 228 | instinit(); |
Rob Pike | 0cafb9e | 2008-06-04 14:37:38 -0700 | [diff] [blame] | 229 | |
| 230 | zprg.link = P; |
| 231 | zprg.pcond = P; |
| 232 | zprg.back = 2; |
| 233 | zprg.as = AGOK; |
| 234 | zprg.from.type = D_NONE; |
| 235 | zprg.from.index = D_NONE; |
| 236 | zprg.from.scale = 1; |
| 237 | zprg.to = zprg.from; |
| 238 | zprg.mode = 64; |
| 239 | |
| 240 | pcstr = "%.6llux "; |
| 241 | nuxiinit(); |
| 242 | histgen = 0; |
Rob Pike | 0cafb9e | 2008-06-04 14:37:38 -0700 | [diff] [blame] | 243 | pc = 0; |
| 244 | dtype = 4; |
Rob Pike | 0cafb9e | 2008-06-04 14:37:38 -0700 | [diff] [blame] | 245 | version = 0; |
| 246 | cbp = buf.cbuf; |
| 247 | cbc = sizeof(buf.cbuf); |
Rob Pike | 0cafb9e | 2008-06-04 14:37:38 -0700 | [diff] [blame] | 248 | |
Russ Cox | 00f4c6a | 2010-02-03 16:30:45 -0800 | [diff] [blame] | 249 | addlibpath("command line", "command line", argv[0], "main"); |
Kai Backman | 2f1a321 | 2010-02-03 22:31:38 -0800 | [diff] [blame] | 250 | loadlib(); |
Russ Cox | c3fa54c | 2009-01-21 14:50:27 -0800 | [diff] [blame] | 251 | deadcode(); |
Rob Pike | 0cafb9e | 2008-06-04 14:37:38 -0700 | [diff] [blame] | 252 | patch(); |
| 253 | follow(); |
Russ Cox | 0e25c1d | 2009-08-21 13:08:11 -0700 | [diff] [blame] | 254 | doelf(); |
Russ Cox | 133a158 | 2009-10-03 10:37:12 -0700 | [diff] [blame] | 255 | if(HEADTYPE == 6) |
| 256 | domacho(); |
Rob Pike | 0cafb9e | 2008-06-04 14:37:38 -0700 | [diff] [blame] | 257 | dostkoff(); |
| 258 | paramspace = "SP"; /* (FP) now (SP) on output */ |
| 259 | if(debug['p']) |
| 260 | if(debug['1']) |
| 261 | doprof1(); |
| 262 | else |
| 263 | doprof2(); |
| 264 | span(); |
Wei Guangjing | 3aec551 | 2011-01-20 09:21:10 -0500 | [diff] [blame] | 265 | if(HEADTYPE == 10) |
| 266 | dope(); |
Russ Cox | 33405ec | 2010-12-15 17:20:26 -0500 | [diff] [blame] | 267 | addexport(); |
Russ Cox | 8132f1d | 2010-12-08 13:53:07 -0500 | [diff] [blame] | 268 | textaddress(); |
Russ Cox | 19fd5c7 | 2010-10-19 18:07:19 -0400 | [diff] [blame] | 269 | pclntab(); |
| 270 | symtab(); |
Russ Cox | 01df088 | 2010-10-19 13:08:17 -0400 | [diff] [blame] | 271 | dodata(); |
| 272 | address(); |
Russ Cox | be2c212 | 2010-10-14 23:48:40 -0400 | [diff] [blame] | 273 | reloc(); |
Rob Pike | 0cafb9e | 2008-06-04 14:37:38 -0700 | [diff] [blame] | 274 | asmb(); |
| 275 | undef(); |
| 276 | if(debug['v']) { |
| 277 | Bprint(&bso, "%5.2f cpu time\n", cputime()); |
Russ Cox | d9c989f | 2010-10-13 16:20:22 -0400 | [diff] [blame] | 278 | Bprint(&bso, "%d symbols\n", nsymbol); |
Rob Pike | 0cafb9e | 2008-06-04 14:37:38 -0700 | [diff] [blame] | 279 | Bprint(&bso, "%d sizeof adr\n", sizeof(Adr)); |
| 280 | Bprint(&bso, "%d sizeof prog\n", sizeof(Prog)); |
| 281 | } |
| 282 | Bflush(&bso); |
| 283 | |
| 284 | errorexit(); |
| 285 | } |
| 286 | |
Russ Cox | 085be17 | 2010-10-13 15:51:21 -0400 | [diff] [blame] | 287 | static Sym* |
Russ Cox | 916f896 | 2010-07-21 13:44:49 -0700 | [diff] [blame] | 288 | zsym(char *pn, Biobuf *f, Sym *h[]) |
| 289 | { |
| 290 | int o; |
| 291 | |
| 292 | o = Bgetc(f); |
| 293 | if(o < 0 || o >= NSYM || h[o] == nil) |
| 294 | mangle(pn); |
| 295 | return h[o]; |
| 296 | } |
| 297 | |
Russ Cox | 085be17 | 2010-10-13 15:51:21 -0400 | [diff] [blame] | 298 | static void |
Russ Cox | e692977 | 2010-07-16 16:16:17 -0700 | [diff] [blame] | 299 | zaddr(char *pn, Biobuf *f, Adr *a, Sym *h[]) |
Russ Cox | a570eaa | 2008-10-20 17:33:51 -0700 | [diff] [blame] | 300 | { |
Russ Cox | 916f896 | 2010-07-21 13:44:49 -0700 | [diff] [blame] | 301 | int t; |
Russ Cox | 9aad9fe | 2008-08-03 17:25:15 -0700 | [diff] [blame] | 302 | int32 l; |
Rob Pike | 0cafb9e | 2008-06-04 14:37:38 -0700 | [diff] [blame] | 303 | Sym *s; |
| 304 | Auto *u; |
| 305 | |
Russ Cox | a570eaa | 2008-10-20 17:33:51 -0700 | [diff] [blame] | 306 | t = Bgetc(f); |
Ken Thompson | 9c75354 | 2009-11-04 18:17:57 -0800 | [diff] [blame] | 307 | a->index = D_NONE; |
| 308 | a->scale = 0; |
Rob Pike | 0cafb9e | 2008-06-04 14:37:38 -0700 | [diff] [blame] | 309 | if(t & T_INDEX) { |
Russ Cox | a570eaa | 2008-10-20 17:33:51 -0700 | [diff] [blame] | 310 | a->index = Bgetc(f); |
| 311 | a->scale = Bgetc(f); |
Rob Pike | 0cafb9e | 2008-06-04 14:37:38 -0700 | [diff] [blame] | 312 | } |
| 313 | a->offset = 0; |
| 314 | if(t & T_OFFSET) { |
Russ Cox | a570eaa | 2008-10-20 17:33:51 -0700 | [diff] [blame] | 315 | a->offset = Bget4(f); |
Rob Pike | 0cafb9e | 2008-06-04 14:37:38 -0700 | [diff] [blame] | 316 | if(t & T_64) { |
Russ Cox | a570eaa | 2008-10-20 17:33:51 -0700 | [diff] [blame] | 317 | a->offset &= 0xFFFFFFFFULL; |
| 318 | a->offset |= (vlong)Bget4(f) << 32; |
Rob Pike | 0cafb9e | 2008-06-04 14:37:38 -0700 | [diff] [blame] | 319 | } |
| 320 | } |
| 321 | a->sym = S; |
Russ Cox | 916f896 | 2010-07-21 13:44:49 -0700 | [diff] [blame] | 322 | if(t & T_SYM) |
| 323 | a->sym = zsym(pn, f, h); |
Rob Pike | 0cafb9e | 2008-06-04 14:37:38 -0700 | [diff] [blame] | 324 | a->type = D_NONE; |
| 325 | if(t & T_FCONST) { |
Russ Cox | a570eaa | 2008-10-20 17:33:51 -0700 | [diff] [blame] | 326 | a->ieee.l = Bget4(f); |
| 327 | a->ieee.h = Bget4(f); |
Rob Pike | 0cafb9e | 2008-06-04 14:37:38 -0700 | [diff] [blame] | 328 | a->type = D_FCONST; |
| 329 | } else |
| 330 | if(t & T_SCONST) { |
Russ Cox | a570eaa | 2008-10-20 17:33:51 -0700 | [diff] [blame] | 331 | Bread(f, a->scon, NSNAME); |
Rob Pike | 0cafb9e | 2008-06-04 14:37:38 -0700 | [diff] [blame] | 332 | a->type = D_SCONST; |
| 333 | } |
Russ Cox | a570eaa | 2008-10-20 17:33:51 -0700 | [diff] [blame] | 334 | if(t & T_TYPE) |
| 335 | a->type = Bgetc(f); |
Russ Cox | 9a44221 | 2010-07-26 17:34:02 -0700 | [diff] [blame] | 336 | if(a->type < 0 || a->type >= D_SIZE) |
| 337 | mangle(pn); |
Ken Thompson | 9c75354 | 2009-11-04 18:17:57 -0800 | [diff] [blame] | 338 | adrgotype = S; |
Russ Cox | 43f29e6 | 2009-08-12 18:16:24 -0700 | [diff] [blame] | 339 | if(t & T_GOTYPE) |
Russ Cox | 916f896 | 2010-07-21 13:44:49 -0700 | [diff] [blame] | 340 | adrgotype = zsym(pn, f, h); |
Rob Pike | 0cafb9e | 2008-06-04 14:37:38 -0700 | [diff] [blame] | 341 | s = a->sym; |
Rob Pike | 0cafb9e | 2008-06-04 14:37:38 -0700 | [diff] [blame] | 342 | t = a->type; |
Russ Cox | e473f42 | 2010-08-04 17:50:22 -0700 | [diff] [blame] | 343 | if(t == D_INDIR+D_GS) |
| 344 | a->offset += tlsoffset; |
Russ Cox | 311c0b4 | 2009-08-13 14:41:42 -0700 | [diff] [blame] | 345 | if(t != D_AUTO && t != D_PARAM) { |
Russ Cox | 9a44221 | 2010-07-26 17:34:02 -0700 | [diff] [blame] | 346 | if(s && adrgotype) |
Ken Thompson | 9c75354 | 2009-11-04 18:17:57 -0800 | [diff] [blame] | 347 | s->gotype = adrgotype; |
Russ Cox | a570eaa | 2008-10-20 17:33:51 -0700 | [diff] [blame] | 348 | return; |
Russ Cox | 311c0b4 | 2009-08-13 14:41:42 -0700 | [diff] [blame] | 349 | } |
Rob Pike | 0cafb9e | 2008-06-04 14:37:38 -0700 | [diff] [blame] | 350 | l = a->offset; |
| 351 | for(u=curauto; u; u=u->link) { |
| 352 | if(u->asym == s) |
| 353 | if(u->type == t) { |
| 354 | if(u->aoffset > l) |
| 355 | u->aoffset = l; |
Ken Thompson | 9c75354 | 2009-11-04 18:17:57 -0800 | [diff] [blame] | 356 | if(adrgotype) |
| 357 | u->gotype = adrgotype; |
Russ Cox | a570eaa | 2008-10-20 17:33:51 -0700 | [diff] [blame] | 358 | return; |
Rob Pike | 0cafb9e | 2008-06-04 14:37:38 -0700 | [diff] [blame] | 359 | } |
| 360 | } |
| 361 | |
| 362 | u = mal(sizeof(*u)); |
| 363 | u->link = curauto; |
| 364 | curauto = u; |
| 365 | u->asym = s; |
| 366 | u->aoffset = l; |
| 367 | u->type = t; |
Ken Thompson | 9c75354 | 2009-11-04 18:17:57 -0800 | [diff] [blame] | 368 | u->gotype = adrgotype; |
Rob Pike | 0cafb9e | 2008-06-04 14:37:38 -0700 | [diff] [blame] | 369 | } |
| 370 | |
| 371 | void |
Rob Pike | 0cafb9e | 2008-06-04 14:37:38 -0700 | [diff] [blame] | 372 | nopout(Prog *p) |
| 373 | { |
| 374 | p->as = ANOP; |
| 375 | p->from.type = D_NONE; |
| 376 | p->to.type = D_NONE; |
| 377 | } |
| 378 | |
Rob Pike | 0cafb9e | 2008-06-04 14:37:38 -0700 | [diff] [blame] | 379 | void |
Russ Cox | 758f2bc | 2010-01-22 17:06:20 -0800 | [diff] [blame] | 380 | ldobj1(Biobuf *f, char *pkg, int64 len, char *pn) |
Rob Pike | 0cafb9e | 2008-06-04 14:37:38 -0700 | [diff] [blame] | 381 | { |
| 382 | vlong ipc; |
Russ Cox | be2c212 | 2010-10-14 23:48:40 -0400 | [diff] [blame] | 383 | Prog *p; |
Rob Pike | 0cafb9e | 2008-06-04 14:37:38 -0700 | [diff] [blame] | 384 | int v, o, r, skip, mode; |
| 385 | Sym *h[NSYM], *s, *di; |
Russ Cox | 9aad9fe | 2008-08-03 17:25:15 -0700 | [diff] [blame] | 386 | uint32 sig; |
Russ Cox | 758f2bc | 2010-01-22 17:06:20 -0800 | [diff] [blame] | 387 | char *name, *x; |
Russ Cox | c287497 | 2009-10-07 00:11:59 -0700 | [diff] [blame] | 388 | int ntext; |
Russ Cox | a570eaa | 2008-10-20 17:33:51 -0700 | [diff] [blame] | 389 | vlong eof; |
Russ Cox | c5f21c0 | 2008-11-13 13:42:26 -0800 | [diff] [blame] | 390 | char src[1024]; |
Russ Cox | 085be17 | 2010-10-13 15:51:21 -0400 | [diff] [blame] | 391 | Prog *lastp; |
Russ Cox | a570eaa | 2008-10-20 17:33:51 -0700 | [diff] [blame] | 392 | |
Russ Cox | 085be17 | 2010-10-13 15:51:21 -0400 | [diff] [blame] | 393 | lastp = nil; |
Rob Pike | d5f4d94 | 2008-07-09 16:40:11 -0700 | [diff] [blame] | 394 | ntext = 0; |
Russ Cox | c287497 | 2009-10-07 00:11:59 -0700 | [diff] [blame] | 395 | eof = Boffset(f) + len; |
Rob Pike | 0cafb9e | 2008-06-04 14:37:38 -0700 | [diff] [blame] | 396 | di = S; |
Russ Cox | c287497 | 2009-10-07 00:11:59 -0700 | [diff] [blame] | 397 | src[0] = 0; |
Rob Pike | 0cafb9e | 2008-06-04 14:37:38 -0700 | [diff] [blame] | 398 | |
| 399 | newloop: |
| 400 | memset(h, 0, sizeof(h)); |
| 401 | version++; |
| 402 | histfrogp = 0; |
| 403 | ipc = pc; |
| 404 | skip = 0; |
| 405 | mode = 64; |
| 406 | |
| 407 | loop: |
Russ Cox | a570eaa | 2008-10-20 17:33:51 -0700 | [diff] [blame] | 408 | if(f->state == Bracteof || Boffset(f) >= eof) |
Rob Pike | 0cafb9e | 2008-06-04 14:37:38 -0700 | [diff] [blame] | 409 | goto eof; |
Russ Cox | a570eaa | 2008-10-20 17:33:51 -0700 | [diff] [blame] | 410 | o = Bgetc(f); |
| 411 | if(o == Beof) |
| 412 | goto eof; |
| 413 | o |= Bgetc(f) << 8; |
Rob Pike | 0cafb9e | 2008-06-04 14:37:38 -0700 | [diff] [blame] | 414 | if(o <= AXXX || o >= ALAST) { |
| 415 | if(o < 0) |
| 416 | goto eof; |
Russ Cox | a570eaa | 2008-10-20 17:33:51 -0700 | [diff] [blame] | 417 | diag("%s:#%lld: opcode out of range: %#ux", pn, Boffset(f), o); |
Rob Pike | 0cafb9e | 2008-06-04 14:37:38 -0700 | [diff] [blame] | 418 | print(" probably not a .6 file\n"); |
| 419 | errorexit(); |
| 420 | } |
| 421 | |
| 422 | if(o == ANAME || o == ASIGNAME) { |
| 423 | sig = 0; |
Russ Cox | a570eaa | 2008-10-20 17:33:51 -0700 | [diff] [blame] | 424 | if(o == ASIGNAME) |
| 425 | sig = Bget4(f); |
| 426 | v = Bgetc(f); /* type */ |
| 427 | o = Bgetc(f); /* sym */ |
Rob Pike | 0cafb9e | 2008-06-04 14:37:38 -0700 | [diff] [blame] | 428 | r = 0; |
| 429 | if(v == D_STATIC) |
| 430 | r = version; |
Russ Cox | a570eaa | 2008-10-20 17:33:51 -0700 | [diff] [blame] | 431 | name = Brdline(f, '\0'); |
| 432 | if(name == nil) { |
| 433 | if(Blinelen(f) > 0) { |
| 434 | fprint(2, "%s: name too long\n", pn); |
| 435 | errorexit(); |
| 436 | } |
| 437 | goto eof; |
| 438 | } |
Russ Cox | 758f2bc | 2010-01-22 17:06:20 -0800 | [diff] [blame] | 439 | x = expandpkg(name, pkg); |
| 440 | s = lookup(x, r); |
| 441 | if(x != name) |
| 442 | free(x); |
| 443 | name = nil; |
Rob Pike | 0cafb9e | 2008-06-04 14:37:38 -0700 | [diff] [blame] | 444 | |
| 445 | if(debug['S'] && r == 0) |
| 446 | sig = 1729; |
| 447 | if(sig != 0){ |
| 448 | if(s->sig != 0 && s->sig != sig) |
Ken Thompson | ddba96a | 2008-06-18 22:07:09 -0700 | [diff] [blame] | 449 | diag("incompatible type signatures" |
Russ Cox | d9c989f | 2010-10-13 16:20:22 -0400 | [diff] [blame] | 450 | "%ux(%s) and %ux(%s) for %s", |
Russ Cox | c287497 | 2009-10-07 00:11:59 -0700 | [diff] [blame] | 451 | s->sig, s->file, sig, pn, s->name); |
Rob Pike | 0cafb9e | 2008-06-04 14:37:38 -0700 | [diff] [blame] | 452 | s->sig = sig; |
Russ Cox | c287497 | 2009-10-07 00:11:59 -0700 | [diff] [blame] | 453 | s->file = pn; |
Rob Pike | 0cafb9e | 2008-06-04 14:37:38 -0700 | [diff] [blame] | 454 | } |
| 455 | |
| 456 | if(debug['W']) |
| 457 | print(" ANAME %s\n", s->name); |
Russ Cox | 916f896 | 2010-07-21 13:44:49 -0700 | [diff] [blame] | 458 | if(o < 0 || o >= nelem(h)) |
| 459 | mangle(pn); |
Rob Pike | 0cafb9e | 2008-06-04 14:37:38 -0700 | [diff] [blame] | 460 | h[o] = s; |
Russ Cox | fc8dca9 | 2009-02-05 13:58:43 -0800 | [diff] [blame] | 461 | if((v == D_EXTERN || v == D_STATIC) && s->type == 0) |
Rob Pike | 0cafb9e | 2008-06-04 14:37:38 -0700 | [diff] [blame] | 462 | s->type = SXREF; |
| 463 | if(v == D_FILE) { |
| 464 | if(s->type != SFILE) { |
| 465 | histgen++; |
| 466 | s->type = SFILE; |
| 467 | s->value = histgen; |
| 468 | } |
| 469 | if(histfrogp < MAXHIST) { |
| 470 | histfrog[histfrogp] = s; |
| 471 | histfrogp++; |
| 472 | } else |
| 473 | collapsefrog(s); |
Russ Cox | d64a2bd | 2010-09-14 11:16:57 -0400 | [diff] [blame] | 474 | dwarfaddfrag(s->value, s->name); |
Rob Pike | 0cafb9e | 2008-06-04 14:37:38 -0700 | [diff] [blame] | 475 | } |
| 476 | goto loop; |
| 477 | } |
| 478 | |
| 479 | p = mal(sizeof(*p)); |
| 480 | p->as = o; |
Russ Cox | a570eaa | 2008-10-20 17:33:51 -0700 | [diff] [blame] | 481 | p->line = Bget4(f); |
Rob Pike | 0cafb9e | 2008-06-04 14:37:38 -0700 | [diff] [blame] | 482 | p->back = 2; |
| 483 | p->mode = mode; |
Ken Thompson | 9c75354 | 2009-11-04 18:17:57 -0800 | [diff] [blame] | 484 | p->ft = 0; |
| 485 | p->tt = 0; |
Russ Cox | e692977 | 2010-07-16 16:16:17 -0700 | [diff] [blame] | 486 | zaddr(pn, f, &p->from, h); |
Ken Thompson | 9c75354 | 2009-11-04 18:17:57 -0800 | [diff] [blame] | 487 | fromgotype = adrgotype; |
Russ Cox | e692977 | 2010-07-16 16:16:17 -0700 | [diff] [blame] | 488 | zaddr(pn, f, &p->to, h); |
Russ Cox | 9a44221 | 2010-07-26 17:34:02 -0700 | [diff] [blame] | 489 | |
| 490 | switch(p->as) { |
| 491 | case ATEXT: |
| 492 | case ADATA: |
| 493 | case AGLOBL: |
| 494 | if(p->from.sym == S) |
| 495 | mangle(pn); |
| 496 | break; |
| 497 | } |
Rob Pike | 0cafb9e | 2008-06-04 14:37:38 -0700 | [diff] [blame] | 498 | |
| 499 | if(debug['W']) |
| 500 | print("%P\n", p); |
| 501 | |
| 502 | switch(p->as) { |
| 503 | case AHISTORY: |
| 504 | if(p->to.offset == -1) { |
Russ Cox | c5f21c0 | 2008-11-13 13:42:26 -0800 | [diff] [blame] | 505 | addlib(src, pn); |
Rob Pike | 0cafb9e | 2008-06-04 14:37:38 -0700 | [diff] [blame] | 506 | histfrogp = 0; |
| 507 | goto loop; |
| 508 | } |
Russ Cox | c5f21c0 | 2008-11-13 13:42:26 -0800 | [diff] [blame] | 509 | if(src[0] == '\0') |
| 510 | copyhistfrog(src, sizeof src); |
Rob Pike | 0cafb9e | 2008-06-04 14:37:38 -0700 | [diff] [blame] | 511 | addhist(p->line, D_FILE); /* 'z' */ |
| 512 | if(p->to.offset) |
| 513 | addhist(p->to.offset, D_FILE1); /* 'Z' */ |
| 514 | histfrogp = 0; |
| 515 | goto loop; |
| 516 | |
| 517 | case AEND: |
| 518 | histtoauto(); |
Russ Cox | 085be17 | 2010-10-13 15:51:21 -0400 | [diff] [blame] | 519 | if(cursym != nil && cursym->text) |
| 520 | cursym->autom = curauto; |
Rob Pike | 0cafb9e | 2008-06-04 14:37:38 -0700 | [diff] [blame] | 521 | curauto = 0; |
Russ Cox | 085be17 | 2010-10-13 15:51:21 -0400 | [diff] [blame] | 522 | cursym = nil; |
Russ Cox | a570eaa | 2008-10-20 17:33:51 -0700 | [diff] [blame] | 523 | if(Boffset(f) == eof) |
| 524 | return; |
| 525 | goto newloop; |
Rob Pike | 0cafb9e | 2008-06-04 14:37:38 -0700 | [diff] [blame] | 526 | |
| 527 | case AGLOBL: |
| 528 | s = p->from.sym; |
| 529 | if(s->type == 0 || s->type == SXREF) { |
| 530 | s->type = SBSS; |
Russ Cox | 698fb4f | 2010-09-12 00:17:44 -0400 | [diff] [blame] | 531 | s->size = 0; |
Rob Pike | 0cafb9e | 2008-06-04 14:37:38 -0700 | [diff] [blame] | 532 | } |
Russ Cox | 698fb4f | 2010-09-12 00:17:44 -0400 | [diff] [blame] | 533 | if(s->type != SBSS && !s->dupok) { |
Rob Pike | 0cafb9e | 2008-06-04 14:37:38 -0700 | [diff] [blame] | 534 | diag("%s: redefinition: %s in %s", |
| 535 | pn, s->name, TNAME); |
| 536 | s->type = SBSS; |
Russ Cox | 698fb4f | 2010-09-12 00:17:44 -0400 | [diff] [blame] | 537 | s->size = 0; |
Rob Pike | 0cafb9e | 2008-06-04 14:37:38 -0700 | [diff] [blame] | 538 | } |
Russ Cox | 698fb4f | 2010-09-12 00:17:44 -0400 | [diff] [blame] | 539 | if(p->to.offset > s->size) |
| 540 | s->size = p->to.offset; |
Russ Cox | 1983121 | 2008-11-05 11:27:50 -0800 | [diff] [blame] | 541 | if(p->from.scale & DUPOK) |
| 542 | s->dupok = 1; |
Russ Cox | 698fb4f | 2010-09-12 00:17:44 -0400 | [diff] [blame] | 543 | if(p->from.scale & RODATA) |
| 544 | s->type = SRODATA; |
Rob Pike | 0cafb9e | 2008-06-04 14:37:38 -0700 | [diff] [blame] | 545 | goto loop; |
| 546 | |
Rob Pike | 0cafb9e | 2008-06-04 14:37:38 -0700 | [diff] [blame] | 547 | case ADATA: |
Russ Cox | 1983121 | 2008-11-05 11:27:50 -0800 | [diff] [blame] | 548 | // Assume that AGLOBL comes after ADATA. |
| 549 | // If we've seen an AGLOBL that said this sym was DUPOK, |
| 550 | // ignore any more ADATA we see, which must be |
| 551 | // redefinitions. |
Russ Cox | c3fa54c | 2009-01-21 14:50:27 -0800 | [diff] [blame] | 552 | s = p->from.sym; |
Russ Cox | be2c212 | 2010-10-14 23:48:40 -0400 | [diff] [blame] | 553 | if(s->dupok) { |
Ken Thompson | 9c75354 | 2009-11-04 18:17:57 -0800 | [diff] [blame] | 554 | // if(debug['v']) |
| 555 | // Bprint(&bso, "skipping %s in %s: dupok\n", s->name, pn); |
Russ Cox | 1983121 | 2008-11-05 11:27:50 -0800 | [diff] [blame] | 556 | goto loop; |
Russ Cox | 8f14451 | 2009-01-20 13:21:22 -0800 | [diff] [blame] | 557 | } |
Russ Cox | be2c212 | 2010-10-14 23:48:40 -0400 | [diff] [blame] | 558 | if(s->file == nil) |
| 559 | s->file = pn; |
| 560 | else if(s->file != pn) { |
| 561 | diag("multiple initialization for %s: in both %s and %s", s->name, s->file, pn); |
| 562 | errorexit(); |
Russ Cox | c3fa54c | 2009-01-21 14:50:27 -0800 | [diff] [blame] | 563 | } |
Russ Cox | be2c212 | 2010-10-14 23:48:40 -0400 | [diff] [blame] | 564 | savedata(s, p); |
| 565 | unmal(p, sizeof *p); |
Rob Pike | 0cafb9e | 2008-06-04 14:37:38 -0700 | [diff] [blame] | 566 | goto loop; |
| 567 | |
| 568 | case AGOK: |
| 569 | diag("%s: GOK opcode in %s", pn, TNAME); |
| 570 | pc++; |
| 571 | goto loop; |
| 572 | |
| 573 | case ATEXT: |
Rob Pike | d5f4d94 | 2008-07-09 16:40:11 -0700 | [diff] [blame] | 574 | s = p->from.sym; |
Russ Cox | 085be17 | 2010-10-13 15:51:21 -0400 | [diff] [blame] | 575 | if(s->text != nil) { |
| 576 | diag("%s: %s: redefinition", pn, s->name); |
| 577 | return; |
| 578 | } |
Russ Cox | fc8dca9 | 2009-02-05 13:58:43 -0800 | [diff] [blame] | 579 | if(ntext++ == 0 && s->type != 0 && s->type != SXREF) { |
Rob Pike | d5f4d94 | 2008-07-09 16:40:11 -0700 | [diff] [blame] | 580 | /* redefinition, so file has probably been seen before */ |
| 581 | if(debug['v']) |
Russ Cox | 8f14451 | 2009-01-20 13:21:22 -0800 | [diff] [blame] | 582 | Bprint(&bso, "skipping: %s: redefinition: %s", pn, s->name); |
Rob Pike | d5f4d94 | 2008-07-09 16:40:11 -0700 | [diff] [blame] | 583 | return; |
| 584 | } |
Russ Cox | 085be17 | 2010-10-13 15:51:21 -0400 | [diff] [blame] | 585 | if(cursym != nil && cursym->text) { |
Rob Pike | 0cafb9e | 2008-06-04 14:37:38 -0700 | [diff] [blame] | 586 | histtoauto(); |
Russ Cox | 085be17 | 2010-10-13 15:51:21 -0400 | [diff] [blame] | 587 | cursym->autom = curauto; |
Rob Pike | 0cafb9e | 2008-06-04 14:37:38 -0700 | [diff] [blame] | 588 | curauto = 0; |
| 589 | } |
| 590 | skip = 0; |
Russ Cox | 085be17 | 2010-10-13 15:51:21 -0400 | [diff] [blame] | 591 | if(etextp) |
| 592 | etextp->next = s; |
| 593 | else |
| 594 | textp = s; |
| 595 | etextp = s; |
| 596 | s->text = p; |
| 597 | cursym = s; |
Russ Cox | fc8dca9 | 2009-02-05 13:58:43 -0800 | [diff] [blame] | 598 | if(s->type != 0 && s->type != SXREF) { |
Rob Pike | 0cafb9e | 2008-06-04 14:37:38 -0700 | [diff] [blame] | 599 | if(p->from.scale & DUPOK) { |
| 600 | skip = 1; |
| 601 | goto casdef; |
| 602 | } |
| 603 | diag("%s: redefinition: %s\n%P", pn, s->name, p); |
| 604 | } |
Ken Thompson | 9c75354 | 2009-11-04 18:17:57 -0800 | [diff] [blame] | 605 | if(fromgotype) { |
| 606 | if(s->gotype && s->gotype != fromgotype) |
Russ Cox | 311c0b4 | 2009-08-13 14:41:42 -0700 | [diff] [blame] | 607 | diag("%s: type mismatch for %s", pn, s->name); |
Ken Thompson | 9c75354 | 2009-11-04 18:17:57 -0800 | [diff] [blame] | 608 | s->gotype = fromgotype; |
Russ Cox | 311c0b4 | 2009-08-13 14:41:42 -0700 | [diff] [blame] | 609 | } |
Russ Cox | 085be17 | 2010-10-13 15:51:21 -0400 | [diff] [blame] | 610 | s->type = STEXT; |
| 611 | s->value = pc; |
| 612 | lastp = p; |
| 613 | p->pc = pc++; |
Rob Pike | 0cafb9e | 2008-06-04 14:37:38 -0700 | [diff] [blame] | 614 | goto loop; |
| 615 | |
| 616 | case AMODE: |
| 617 | if(p->from.type == D_CONST || p->from.type == D_INDIR+D_NONE){ |
| 618 | switch((int)p->from.offset){ |
| 619 | case 16: case 32: case 64: |
| 620 | mode = p->from.offset; |
| 621 | break; |
| 622 | } |
| 623 | } |
| 624 | goto loop; |
| 625 | |
| 626 | case AFMOVF: |
| 627 | case AFADDF: |
| 628 | case AFSUBF: |
| 629 | case AFSUBRF: |
| 630 | case AFMULF: |
| 631 | case AFDIVF: |
| 632 | case AFDIVRF: |
| 633 | case AFCOMF: |
| 634 | case AFCOMFP: |
| 635 | case AMOVSS: |
| 636 | case AADDSS: |
| 637 | case ASUBSS: |
| 638 | case AMULSS: |
| 639 | case ADIVSS: |
| 640 | case ACOMISS: |
| 641 | case AUCOMISS: |
| 642 | if(skip) |
| 643 | goto casdef; |
| 644 | if(p->from.type == D_FCONST) { |
| 645 | /* size sb 9 max */ |
Russ Cox | d9c989f | 2010-10-13 16:20:22 -0400 | [diff] [blame] | 646 | sprint(literal, "$%ux", ieeedtof(&p->from.ieee)); |
Rob Pike | 0cafb9e | 2008-06-04 14:37:38 -0700 | [diff] [blame] | 647 | s = lookup(literal, 0); |
| 648 | if(s->type == 0) { |
Russ Cox | be2c212 | 2010-10-14 23:48:40 -0400 | [diff] [blame] | 649 | s->type = SDATA; |
| 650 | adduint32(s, ieeedtof(&p->from.ieee)); |
Russ Cox | 8132f1d | 2010-12-08 13:53:07 -0500 | [diff] [blame] | 651 | s->reachable = 0; |
Rob Pike | 0cafb9e | 2008-06-04 14:37:38 -0700 | [diff] [blame] | 652 | } |
| 653 | p->from.type = D_EXTERN; |
| 654 | p->from.sym = s; |
| 655 | p->from.offset = 0; |
| 656 | } |
| 657 | goto casdef; |
| 658 | |
| 659 | case AFMOVD: |
| 660 | case AFADDD: |
| 661 | case AFSUBD: |
| 662 | case AFSUBRD: |
| 663 | case AFMULD: |
| 664 | case AFDIVD: |
| 665 | case AFDIVRD: |
| 666 | case AFCOMD: |
| 667 | case AFCOMDP: |
| 668 | case AMOVSD: |
| 669 | case AADDSD: |
| 670 | case ASUBSD: |
| 671 | case AMULSD: |
| 672 | case ADIVSD: |
| 673 | case ACOMISD: |
| 674 | case AUCOMISD: |
| 675 | if(skip) |
| 676 | goto casdef; |
| 677 | if(p->from.type == D_FCONST) { |
| 678 | /* size sb 18 max */ |
Russ Cox | d9c989f | 2010-10-13 16:20:22 -0400 | [diff] [blame] | 679 | sprint(literal, "$%ux.%ux", |
Rob Pike | 0cafb9e | 2008-06-04 14:37:38 -0700 | [diff] [blame] | 680 | p->from.ieee.l, p->from.ieee.h); |
| 681 | s = lookup(literal, 0); |
| 682 | if(s->type == 0) { |
Russ Cox | be2c212 | 2010-10-14 23:48:40 -0400 | [diff] [blame] | 683 | s->type = SDATA; |
| 684 | adduint32(s, p->from.ieee.l); |
| 685 | adduint32(s, p->from.ieee.h); |
Russ Cox | 8132f1d | 2010-12-08 13:53:07 -0500 | [diff] [blame] | 686 | s->reachable = 0; |
Rob Pike | 0cafb9e | 2008-06-04 14:37:38 -0700 | [diff] [blame] | 687 | } |
| 688 | p->from.type = D_EXTERN; |
| 689 | p->from.sym = s; |
| 690 | p->from.offset = 0; |
| 691 | } |
| 692 | goto casdef; |
| 693 | |
| 694 | casdef: |
| 695 | default: |
| 696 | if(skip) |
| 697 | nopout(p); |
Russ Cox | 085be17 | 2010-10-13 15:51:21 -0400 | [diff] [blame] | 698 | p->pc = pc; |
| 699 | pc++; |
Rob Pike | 0cafb9e | 2008-06-04 14:37:38 -0700 | [diff] [blame] | 700 | |
| 701 | if(p->to.type == D_BRANCH) |
| 702 | p->to.offset += ipc; |
Russ Cox | 085be17 | 2010-10-13 15:51:21 -0400 | [diff] [blame] | 703 | if(lastp == nil) { |
| 704 | if(p->as != ANOP) |
| 705 | diag("unexpected instruction: %P", p); |
| 706 | goto loop; |
| 707 | } |
Rob Pike | 0cafb9e | 2008-06-04 14:37:38 -0700 | [diff] [blame] | 708 | lastp->link = p; |
| 709 | lastp = p; |
Rob Pike | 0cafb9e | 2008-06-04 14:37:38 -0700 | [diff] [blame] | 710 | goto loop; |
| 711 | } |
| 712 | goto loop; |
| 713 | |
| 714 | eof: |
| 715 | diag("truncated object file: %s", pn); |
| 716 | } |
| 717 | |
Rob Pike | 0cafb9e | 2008-06-04 14:37:38 -0700 | [diff] [blame] | 718 | Prog* |
| 719 | prg(void) |
| 720 | { |
| 721 | Prog *p; |
| 722 | |
| 723 | p = mal(sizeof(*p)); |
| 724 | |
| 725 | *p = zprg; |
| 726 | return p; |
| 727 | } |
| 728 | |
| 729 | Prog* |
| 730 | copyp(Prog *q) |
| 731 | { |
| 732 | Prog *p; |
| 733 | |
| 734 | p = prg(); |
| 735 | *p = *q; |
| 736 | return p; |
| 737 | } |
| 738 | |
| 739 | Prog* |
| 740 | appendp(Prog *q) |
| 741 | { |
| 742 | Prog *p; |
| 743 | |
| 744 | p = prg(); |
| 745 | p->link = q->link; |
| 746 | q->link = p; |
| 747 | p->line = q->line; |
| 748 | p->mode = q->mode; |
| 749 | return p; |
| 750 | } |