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