diff options
| author | Cliff Click <cliffc@acm.org> | 2025-04-05 13:58:07 -0700 |
|---|---|---|
| committer | Cliff Click <cliffc@acm.org> | 2025-04-05 13:58:07 -0700 |
| commit | 7277ab049ab9cae5fa64cd5ea958f69278f773a4 (patch) | |
| tree | 55289107814ed0dac39288dd55520aed9a5d66e5 /chapter21/src/main | |
| parent | fc7d2bce649854982a3c16de164bbaafec11bc27 (diff) | |
| download | Simple-7277ab049ab9cae5fa64cd5ea958f69278f773a4.tar.gz Simple-7277ab049ab9cae5fa64cd5ea958f69278f773a4.zip | |
Fix elf constants
Record more relocation info in the machine-specific encodings. Use it when building ELF.
Switch to simpler Newtons; some encoding bug in the complex one.
Diffstat (limited to 'chapter21/src/main')
7 files changed, 60 insertions, 75 deletions
diff --git a/chapter21/src/main/java/com/seaofnodes/simple/codegen/ElfFile.java b/chapter21/src/main/java/com/seaofnodes/simple/codegen/ElfFile.java index 62bcfcde..746ecfed 100644 --- a/chapter21/src/main/java/com/seaofnodes/simple/codegen/ElfFile.java +++ b/chapter21/src/main/java/com/seaofnodes/simple/codegen/ElfFile.java @@ -8,6 +8,7 @@ import java.io.*; import java.nio.ByteBuffer; import java.nio.ByteOrder; import java.util.HashMap; +import java.util.Map; public class ElfFile { @@ -228,30 +229,6 @@ public class ElfFile { } } - public final HashMap<Type, Symbol> _bigCons = new HashMap<>(); - private void encodeConstants(SymbolSection symbols, DataSection rdata) { - int cnt = 0; - for (Map.Entry<Node,Type> e : _code._encoding._bigCons.entrySet()) { - if (_bigCons.get(e.getValue()) != null) { - continue; - } - - Symbol glob = new Symbol("GLOB$"+cnt, rdata._index, SYM_BIND_GLOBAL, SYM_TYPE_FUNC); - glob._value = rdata._contents.size(); - symbols.push(glob); - - Type t = e.getValue(); - if ( t instanceof TypeFloat tf ) { - write8(rdata._contents, Double.doubleToLongBits(tf._con)); - } else { - throw Utils.TODO(); - } - - glob._size = rdata._contents.size() - glob._value; - _bigCons.put(e.getValue(), glob); - cnt++; - } - } public void export(String fname) throws IOException { DataSection strtab = new DataSection(".strtab", 3 /* SHT_SYMTAB */); // first byte is reserved for an empty string @@ -270,15 +247,14 @@ public class ElfFile { // Build and write constant pool BAOS cpool = new BAOS(); - _code._encoding.writeConstantPool(cpool,false); + Encoding enc = _code._encoding; + enc.writeConstantPool(cpool,false); DataSection rdata = new DataSection(".rodata", 1 /* SHT_PROGBITS */, cpool); rdata._flags = SHF_ALLOC; pushSection(rdata); // populate function symbols encodeFunctions(symbols, text); - // populate big constants - encodeConstants(symbols, rdata); int idx = 1; for( Section s : _sections ) { @@ -294,21 +270,23 @@ public class ElfFile { for( Symbol s : symbols._loc ) s._index = num++; // extra space for .rela.text - int start_global = symbols._loc.size(); - for(Symbol a: symbols._symbols) { + int start_global = num+1; // Add one to skip the final .rela.text local symbol + for( Symbol a: symbols._symbols ) a._index = start_global++; + int bigConIdx = start_global; + start_global += enc._bigCons.size(); // create .text relocations DataSection text_rela = new DataSection(".rela.text", 4 /* SHT_RELA */); - for( Node n : _code._encoding._externals.keySet()) { + for( Node n : enc._externals.keySet()) { int nid = n._nid; - String extern = _code._encoding._externals.get(n); + String extern = enc._externals.get(n); Symbol sym = new Symbol(extern, 0, SYM_BIND_GLOBAL, SYM_TYPE_NOTYPE); sym._index = start_global++; symbols.push(sym); - int offset = _code._encoding._opStart[nid] + _code._encoding._opLen[nid] - 4; + int offset = enc._opStart[nid] + enc._opLen[nid] - 4; // u64 offset write8(text_rela._contents, offset); @@ -318,17 +296,15 @@ public class ElfFile { write8(text_rela._contents, -4); } - // relocations to constants - for (Map.Entry<Node,Type> e : _code._encoding._bigCons.entrySet()) { - int nid = e.getKey()._nid; - int sym_id = _bigCons.get(e.getValue())._index; - int offset = _code._encoding._opStart[nid] + _code._encoding._opLen[nid] - 4; - - // u64 offset - write8(text_rela._contents, offset); - // u64 info - write8(text_rela._contents, ((long)sym_id << 32L) | 2L /* PC32 */); - // i64 addend + // Write relocations for the constant pool + for( Encoding.Relo relo : enc._bigCons.values() ) { + Symbol glob = new Symbol("GLOB$"+bigConIdx, rdata._index, SYM_BIND_GLOBAL, SYM_TYPE_FUNC); + glob._value = relo._target; + glob._size = 1 << relo._t.log_size(); + glob._index = bigConIdx++; + symbols.push(glob); + write8(text_rela._contents, relo._opStart+relo._off); + write8(text_rela._contents, ((long)glob._index << 32L) | relo._elf ); write8(text_rela._contents, -4); } @@ -337,7 +313,7 @@ public class ElfFile { text_rela._info = text._index; pushSection(text_rela); - Symbol sym = new Symbol(text_rela._name, num, SYM_BIND_LOCAL, SYM_TYPE_SECTION); + Symbol sym = new Symbol(text_rela._name, num++, SYM_BIND_LOCAL, SYM_TYPE_SECTION); sym._name_pos = text_rela._name_pos; sym._size = text_rela.size(); symbols.push(sym); diff --git a/chapter21/src/main/java/com/seaofnodes/simple/codegen/Encoding.java b/chapter21/src/main/java/com/seaofnodes/simple/codegen/Encoding.java index f90ce96a..a66fc579 100644 --- a/chapter21/src/main/java/com/seaofnodes/simple/codegen/Encoding.java +++ b/chapter21/src/main/java/com/seaofnodes/simple/codegen/Encoding.java @@ -44,8 +44,19 @@ public class Encoding { public int [] _opStart; // Start of opcodes, by _nid public byte[] _opLen; // Length of opcodes, by _nid - // Big Constant relocation info - public final HashMap<Node,Type> _bigCons = new HashMap<>(); + // Big Constant relocation info. + public static class Relo { + public final Node _op; + public final Type _t; // Constant type + public final byte _off; // Offset from start of opcode + public final byte _elf; // ELF relocation type, e.g. 2/PC32 + public int _target; // Where constant is finally placede + public int _opStart; // Opcode start + Relo( Node op, Type t, byte off, byte elf ) { + _op=op; _t=t; _off=off; _elf=elf; + } + } + public final HashMap<Node,Relo> _bigCons = new HashMap<>(); Encoding( CodeGen code ) { _code = code; } @@ -135,9 +146,11 @@ public class Encoding { // Store t as a 32/64 bit constant in the code space; generate RIP-relative // addressing to load it - public void largeConstant( Node relo, Type t ) { + public void largeConstant( Node relo, Type t, int off, int elf ) { assert t.isConstant(); - _bigCons.put(relo,t); + assert (byte)off == off; + assert (byte)elf == elf; + _bigCons.put(relo,new Relo(relo,t,(byte)off,(byte)elf)); } void encode() { @@ -151,14 +164,13 @@ public class Encoding { // Record opcode start and length. writeEncodings(); - // ELF handles big constants, they - // are accessed by RIP-relative addressing. - - if(_code._JIT) writeConstantPool(true); // Short-form RIP-relative support: replace long encodings with short // encodings and compact the code, changing all the offsets. compactShortForm(); + // Patch RIP-relative and local encodings now. + patchLocalRelocations(); + } // Basic block layout: invert branches to keep blocks in-order; insert @@ -364,8 +376,8 @@ public class Encoding { // Write the constant pool into the BAOS and optionally patch locally void writeConstantPool( BAOS bits, boolean patch ) { - HashSet<Type> ts = new HashSet<>(); - for( Type t : _bigCons.values() ) { + HashSet<Relo> ts = new HashSet<>(); + for( Relo t : _bigCons.values() ) { if( ts.contains(t) ) throw Utils.TODO(); // Dup! Compress! ts.add(t); @@ -375,21 +387,21 @@ public class Encoding { // By log size for( int log = 3; log >= 0; log-- ) { // Write the 8-byte constants - for( Node relo : _bigCons.keySet() ) { - Type t = _bigCons.get(relo); - if( t.log_size()==log ) { + for( Node op : _bigCons.keySet() ) { + Relo relo = _bigCons.get(op); + if( relo._t.log_size()==log ) { // Map from relo to constant start and patch - if( patch ) { - int target = _bits.size(); - int start = _opStart[relo._nid]; - ((RIPRelSize)relo).patch(this, start, _opLen[relo._nid], target - start); - } + relo._target = bits.size(); + relo._opStart= _opStart[op._nid]; + // Go ahead and locally patch in-memory + if( patch ) + ((RIPRelSize)op).patch(this, relo._opStart, _opLen[op._nid], relo._target - relo._opStart); // Put constant into code space. - if( t instanceof TypeTuple tt ) // Constant tuples put all entries + if( relo._t instanceof TypeTuple tt ) // Constant tuples put all entries for( Type tx : tt._types ) addN(log,tx,bits); else - addN(log,t,bits); + addN(log,relo._t,bits); } } } diff --git a/chapter21/src/main/java/com/seaofnodes/simple/codegen/LinkMem.java b/chapter21/src/main/java/com/seaofnodes/simple/codegen/LinkMem.java index 35d2008a..07a5dd12 100644 --- a/chapter21/src/main/java/com/seaofnodes/simple/codegen/LinkMem.java +++ b/chapter21/src/main/java/com/seaofnodes/simple/codegen/LinkMem.java @@ -10,9 +10,6 @@ public class LinkMem { // are accessed by RIP-relative addressing. _code._encoding.writeConstantPool(_code._encoding._bits,true); - // Patch RIP-relative and local encodings now. - _code._encoding.patchLocalRelocations(); - return _code; } } diff --git a/chapter21/src/main/java/com/seaofnodes/simple/node/cpus/arm/FloatARM.java b/chapter21/src/main/java/com/seaofnodes/simple/node/cpus/arm/FloatARM.java index 45ecc430..dc125af2 100644 --- a/chapter21/src/main/java/com/seaofnodes/simple/node/cpus/arm/FloatARM.java +++ b/chapter21/src/main/java/com/seaofnodes/simple/node/cpus/arm/FloatARM.java @@ -18,7 +18,7 @@ public class FloatARM extends ConstantNode implements MachNode, RIPRelSize { @Override public FloatARM copy() { return new FloatARM(this); } @Override public void encoding( Encoding enc ) { - enc.largeConstant(this,_con); + enc.largeConstant(this,_con,0,-1/*TODO: ARM-style ELF patching*/); short dst = (short)(enc.reg(this) - arm.D_OFFSET); double d = ((TypeFloat)_con).value(); long x = Double.doubleToRawLongBits(d); diff --git a/chapter21/src/main/java/com/seaofnodes/simple/node/cpus/riscv/FltRISC.java b/chapter21/src/main/java/com/seaofnodes/simple/node/cpus/riscv/FltRISC.java index d1bd4a94..0a7b02e3 100644 --- a/chapter21/src/main/java/com/seaofnodes/simple/node/cpus/riscv/FltRISC.java +++ b/chapter21/src/main/java/com/seaofnodes/simple/node/cpus/riscv/FltRISC.java @@ -16,7 +16,7 @@ public class FltRISC extends ConstantNode implements MachNode, RIPRelSize { @Override public FltRISC copy() { return new FltRISC(this); } @Override public void encoding( Encoding enc ) { - enc.largeConstant(this,_con); + enc.largeConstant(this,_con, 0, -1/*TODO: RISC5 style patching*/); short dst = (short)(enc.reg(this) - riscv.F_OFFSET); short tmp = (short)riscv.T6; // AUIPC dst,#hi20_constant_pool diff --git a/chapter21/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/FltX86.java b/chapter21/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/FltX86.java index c9df7b99..e3b20003 100644 --- a/chapter21/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/FltX86.java +++ b/chapter21/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/FltX86.java @@ -19,7 +19,6 @@ public class FltX86 extends ConstantNode implements MachNode, RIPRelSize{ // F2 0F 10 /r MOVSD xmm1, m64 _encSize = 1/*Fop*/+0/*REX*/+2/*op*/+1/*MODRM*/+4/*offset*/; short dst = (short)(enc.reg(this ) - x86_64_v2.XMM_OFFSET); - enc.largeConstant(this,_con); // Fopcode enc.add1(0xF2); // rex prefix must come next (REX.W is not set) @@ -28,6 +27,7 @@ public class FltX86 extends ConstantNode implements MachNode, RIPRelSize{ // hard-code rip here enc.add1(x86_64_v2.modrm(x86_64_v2.MOD.INDIRECT, dst, 0x05)); enc.add4(0); + enc.largeConstant(this,_con,_encSize-4,2/*ELF encoding PC32*/); } // Delta is from opcode start diff --git a/chapter21/src/main/java/com/seaofnodes/simple/print/ASMPrinter.java b/chapter21/src/main/java/com/seaofnodes/simple/print/ASMPrinter.java index 2e475f13..c040d414 100644 --- a/chapter21/src/main/java/com/seaofnodes/simple/print/ASMPrinter.java +++ b/chapter21/src/main/java/com/seaofnodes/simple/print/ASMPrinter.java @@ -29,11 +29,11 @@ public abstract class ASMPrinter { sb.p("--- Constant Pool ------").nl(); // By log size for( int log = 3; log >= 0; log-- ) { - for( Node relo : enc._bigCons.keySet() ) { - Type t = enc._bigCons.get(relo); - if( t.log_size()==log ) { + for( Node op : enc._bigCons.keySet() ) { + Encoding.Relo relo = enc._bigCons.get(op); + if( relo._t.log_size()==log ) { sb.hex2(iadr).p(" "); - if( t instanceof TypeTuple tt ) { + if( relo._t instanceof TypeTuple tt ) { for( Type tx : tt._types ) { switch( log ) { case 0: sb.hex1(enc.read1(iadr)); break; @@ -53,7 +53,7 @@ public abstract class ASMPrinter { } iadr += (1<<log); } - t.print(sb).nl(); + relo._t.print(sb).nl(); } } } |
