1 // Inferno utils/5l/asm.c
2 // http://code.google.com/p/inferno-os/source/browse/utils/5l/asm.c
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.
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:
20 // The above copyright notice and this permission notice shall be included in
21 // all copies or substantial portions of the Software.
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
36 "cmd/link/internal/ld"
43 func adddynrel(s *ld.LSym, r *ld.Reloc) {
44 log.Fatalf("adddynrel not implemented")
47 func elfreloc1(r *ld.Reloc, sectoff int64) int {
48 // mips64 ELF relocation (endian neutral)
57 ld.Thearch.Vput(uint64(sectoff))
59 elfsym := r.Xsym.ElfsymForReloc()
60 ld.Thearch.Lput(uint32(elfsym))
79 ld.Cput(ld.R_MIPS_LO16)
82 ld.Cput(ld.R_MIPS_HI16)
84 case obj.R_ADDRMIPSTLS:
85 ld.Cput(ld.R_MIPS_TLS_TPREL_LO16)
91 ld.Thearch.Vput(uint64(r.Xadd))
100 func machoreloc1(r *ld.Reloc, sectoff int64) int {
104 func archreloc(r *ld.Reloc, s *ld.LSym, val *int64) int {
105 if ld.Linkmode == ld.LinkExternal {
114 // set up addend for eventual relocation via outer symbol.
117 for rs.Outer != nil {
118 r.Xadd += ld.Symaddr(rs) - ld.Symaddr(rs.Outer)
122 if rs.Type != obj.SHOSTOBJ && rs.Type != obj.SDYNIMPORT && rs.Sect == nil {
123 ld.Diag("missing section for %s", rs.Name)
129 case obj.R_ADDRMIPSTLS,
145 *val = ld.Symaddr(r.Sym) + r.Add - ld.Symaddr(ld.Linklookup(ld.Ctxt, ".got", 0))
150 t := ld.Symaddr(r.Sym) + r.Add
151 o1 := ld.SysArch.ByteOrder.Uint32(s.P[r.Off:])
152 if r.Type == obj.R_ADDRMIPS {
153 *val = int64(o1&0xffff0000 | uint32(t)&0xffff)
155 *val = int64(o1&0xffff0000 | uint32((t+1<<15)>>16)&0xffff)
159 case obj.R_ADDRMIPSTLS:
160 // thread pointer is at 0x7000 offset from the start of TLS data area
161 t := ld.Symaddr(r.Sym) + r.Add - 0x7000
162 if t < -32768 || t >= 32678 {
163 ld.Diag("TLS offset out of range %d", t)
165 o1 := ld.SysArch.ByteOrder.Uint32(s.P[r.Off:])
166 *val = int64(o1&0xffff0000 | uint32(t)&0xffff)
171 // Low 26 bits = (S + A) >> 2
172 t := ld.Symaddr(r.Sym) + r.Add
173 o1 := ld.SysArch.ByteOrder.Uint32(s.P[r.Off:])
174 *val = int64(o1&0xfc000000 | uint32(t>>2)&^0xfc000000)
181 func archrelocvariant(r *ld.Reloc, s *ld.LSym, t int64) int64 {
186 if ld.Debug['v'] != 0 {
187 fmt.Fprintf(ld.Bso, "%5.2f asmb\n", obj.Cputime())
195 sect := ld.Segtext.Sect
196 ld.Cseek(int64(sect.Vaddr - ld.Segtext.Vaddr + ld.Segtext.Fileoff))
197 ld.Codeblk(int64(sect.Vaddr), int64(sect.Length))
198 for sect = sect.Next; sect != nil; sect = sect.Next {
199 ld.Cseek(int64(sect.Vaddr - ld.Segtext.Vaddr + ld.Segtext.Fileoff))
200 ld.Datblk(int64(sect.Vaddr), int64(sect.Length))
203 if ld.Segrodata.Filelen > 0 {
204 if ld.Debug['v'] != 0 {
205 fmt.Fprintf(ld.Bso, "%5.2f rodatblk\n", obj.Cputime())
209 ld.Cseek(int64(ld.Segrodata.Fileoff))
210 ld.Datblk(int64(ld.Segrodata.Vaddr), int64(ld.Segrodata.Filelen))
213 if ld.Debug['v'] != 0 {
214 fmt.Fprintf(ld.Bso, "%5.2f datblk\n", obj.Cputime())
218 ld.Cseek(int64(ld.Segdata.Fileoff))
219 ld.Datblk(int64(ld.Segdata.Vaddr), int64(ld.Segdata.Filelen))
221 ld.Cseek(int64(ld.Segdwarf.Fileoff))
222 ld.Dwarfblk(int64(ld.Segdwarf.Vaddr), int64(ld.Segdwarf.Filelen))
224 /* output symbol table */
229 if ld.Debug['s'] == 0 {
231 if ld.Debug['v'] != 0 {
232 fmt.Fprintf(ld.Bso, "%5.2f sym\n", obj.Cputime())
238 symo = uint32(ld.Segdwarf.Fileoff + ld.Segdwarf.Filelen)
239 symo = uint32(ld.Rnd(int64(symo), int64(ld.INITRND)))
243 symo = uint32(ld.Segdata.Fileoff + ld.Segdata.Filelen)
246 ld.Cseek(int64(symo))
250 if ld.Debug['v'] != 0 {
251 fmt.Fprintf(ld.Bso, "%5.2f elfsym\n", obj.Cputime())
255 ld.Cwrite(ld.Elfstrdat)
257 if ld.Linkmode == ld.LinkExternal {
266 sym := ld.Linklookup(ld.Ctxt, "pclntab", 0)
268 ld.Lcsize = int32(len(sym.P))
269 for i := 0; int32(i) < ld.Lcsize; i++ {
279 if ld.Debug['v'] != 0 {
280 fmt.Fprintf(ld.Bso, "%5.2f header\n", obj.Cputime())
286 case obj.Hplan9: /* plan 9 */
287 magic := uint32(4*18*18 + 7)
288 if ld.SysArch == sys.ArchMIPS64LE {
289 magic = uint32(4*26*26 + 7)
291 ld.Thearch.Lput(magic) /* magic */
292 ld.Thearch.Lput(uint32(ld.Segtext.Filelen)) /* sizes */
293 ld.Thearch.Lput(uint32(ld.Segdata.Filelen))
294 ld.Thearch.Lput(uint32(ld.Segdata.Length - ld.Segdata.Filelen))
295 ld.Thearch.Lput(uint32(ld.Symsize)) /* nsyms */
296 ld.Thearch.Lput(uint32(ld.Entryvalue())) /* va of entry */
298 ld.Thearch.Lput(uint32(ld.Lcsize))
305 ld.Asmbelf(int64(symo))
309 if ld.Debug['c'] != 0 {
310 fmt.Printf("textsize=%d\n", ld.Segtext.Filelen)
311 fmt.Printf("datsize=%d\n", ld.Segdata.Filelen)
312 fmt.Printf("bsssize=%d\n", ld.Segdata.Length-ld.Segdata.Filelen)
313 fmt.Printf("symsize=%d\n", ld.Symsize)
314 fmt.Printf("lcsize=%d\n", ld.Lcsize)
315 fmt.Printf("total=%d\n", ld.Segtext.Filelen+ld.Segdata.Length+uint64(ld.Symsize)+uint64(ld.Lcsize))