@retrovm/nobj 0.1.2 → 0.1.4

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (2) hide show
  1. package/nobj.ts +182 -159
  2. package/package.json +5 -1
package/nobj.ts CHANGED
@@ -33,19 +33,29 @@ export type TargetArch = 'x64' | 'arm64';
33
33
  /** Align v up to the next multiple of a (a must be a power of two). */
34
34
  const al = (v: number, a: number): number => (v + a - 1) & -a;
35
35
 
36
+ const enc = new TextEncoder();
37
+
36
38
  /**
37
39
  * Write a 64-bit LE uint using two 32-bit writes.
38
40
  * Safe for values ≤ 2^53 (all realistic file offsets and sizes).
39
41
  */
40
- function writeU64(buf: Buffer, off: number, val: number): void {
41
- buf.writeUInt32LE(val >>> 0, off);
42
- buf.writeUInt32LE(Math.floor(val / 0x100000000), off + 4);
42
+ function writeU64(dv: DataView, off: number, val: number): void {
43
+ dv.setUint32(off, val >>> 0, true);
44
+ dv.setUint32(off + 4, Math.floor(val / 0x100000000), true);
43
45
  }
44
46
 
45
47
  /** Zero a char[len] field and write an ASCII string (no overflow). */
46
- function setStr(buf: Buffer, off: number, str: string, len: number): void {
48
+ function setStr(buf: Uint8Array, off: number, str: string, len: number): void {
47
49
  buf.fill(0, off, off + len);
48
- buf.write(str.substring(0, len), off, 'ascii');
50
+ buf.set(enc.encode(str.substring(0, len)), off);
51
+ }
52
+
53
+ function concat(arrays: Uint8Array[]): Uint8Array {
54
+ const total = arrays.reduce((n, a) => n + a.length, 0);
55
+ const out = new Uint8Array(total);
56
+ let ofs = 0;
57
+ for (const a of arrays) { out.set(a, ofs); ofs += a.length; }
58
+ return out;
49
59
  }
50
60
 
51
61
  function hostArch(): TargetArch {
@@ -90,25 +100,29 @@ const COFF_SYM_SZ = 18;
90
100
  const COFF_HDR_SZ = 20;
91
101
  const COFF_SECT_SZ = 40;
92
102
 
93
- function doObjectWindows(symbols: ObjSymbol[], arch: TargetArch): Buffer {
103
+ function doObjectWindows(symbols: ObjSymbol[], arch: TargetArch): Uint8Array {
94
104
  let strTabSz = 0, dataSz = 0;
95
105
  const directives: string[] = [];
96
106
 
97
107
  for (const { name, obj } of symbols) {
98
108
  strTabSz += name.length + 1;
99
109
  directives.push(` /EXPORT:${name},DATA`);
100
- if (obj instanceof Uint8Array) dataSz += al(obj.length, 8);
110
+ if (obj instanceof Uint8Array) dataSz += al(obj.length, 8);
101
111
  else if (typeof obj === 'string') dataSz += al(obj.length + 1, 8);
102
112
  else if (typeof obj === 'number') dataSz += 8;
103
113
  else throw new Error('Invalid symbol type');
104
114
  }
105
115
 
106
- const tsd = Buffer.alloc(strTabSz + 4); // COFF string table
107
- const dsd = Buffer.alloc(dataSz); // .rdata data
108
- const tsed = Buffer.from(directives.join(''), 'ascii'); // .drectve content
109
- const symd = Buffer.alloc(COFF_SYM_SZ * symbols.length); // per-export symbols
116
+ const tsd = new Uint8Array(strTabSz + 4); // COFF string table
117
+ const dsd = new Uint8Array(dataSz); // .rdata data
118
+ const tsed = enc.encode(directives.join('')); // .drectve content
119
+ const symd = new Uint8Array(COFF_SYM_SZ * symbols.length); // per-export symbols
120
+
121
+ const tsddv = new DataView(tsd.buffer);
122
+ const dsddv = new DataView(dsd.buffer);
123
+ const symdv = new DataView(symd.buffer);
110
124
 
111
- tsd.writeUInt32LE(strTabSz + 4, 0); // string table size prefix
125
+ tsddv.setUint32(0, strTabSz + 4, true); // string table size prefix
112
126
 
113
127
  let strOff = 4, dataOff = 0;
114
128
 
@@ -117,87 +131,88 @@ function doObjectWindows(symbols: ObjSymbol[], arch: TargetArch): Buffer {
117
131
  const b = i * COFF_SYM_SZ;
118
132
 
119
133
  // CoffSymbol: long name (zeros=0 means use string table, offset=strOff)
120
- symd.writeUInt32LE(0, b + 0); // name.zeros
121
- symd.writeUInt32LE(strOff, b + 4); // name.offset → string table
122
- symd.writeUInt32LE(dataOff, b + 8); // value = offset in .rdata
123
- symd.writeInt16LE(2, b + 12); // sectionNumber: .rdata = 2
124
- symd.writeUInt16LE(0, b + 14); // type
125
- symd.writeUInt8(0x2, b + 16); // storageClass: IMAGE_SYM_CLASS_EXTERNAL
126
- symd.writeUInt8(0, b + 17); // numberOfAuxSymbols
127
-
128
- tsd.write(name, strOff, 'ascii');
134
+ symdv.setUint32(b + 0, 0, true); // name.zeros
135
+ symdv.setUint32(b + 4, strOff, true); // name.offset → string table
136
+ symdv.setUint32(b + 8, dataOff, true); // value = offset in .rdata
137
+ symdv.setInt16( b + 12, 2, true); // sectionNumber: .rdata = 2
138
+ symdv.setUint16(b + 14, 0, true); // type
139
+ symd[b + 16] = 0x2; // storageClass: IMAGE_SYM_CLASS_EXTERNAL
140
+ symd[b + 17] = 0; // numberOfAuxSymbols
141
+
142
+ tsd.set(enc.encode(name), strOff);
129
143
  strOff += name.length + 1;
130
144
 
131
145
  if (obj instanceof Uint8Array) {
132
146
  dsd.set(obj, dataOff);
133
147
  dataOff += al(obj.length, 8);
134
148
  } else if (typeof obj === 'string') {
135
- dsd.write(obj, dataOff, 'ascii');
149
+ dsd.set(enc.encode(obj), dataOff);
136
150
  dataOff += al(obj.length + 1, 8);
137
151
  } else if (typeof obj === 'number') {
138
- dsd.writeDoubleLE(obj, dataOff);
152
+ dsddv.setFloat64(dataOff, obj, true);
139
153
  dataOff += 8;
140
154
  }
141
155
  }
142
156
 
143
157
  // ── Coff header struct ──────────────────────────────────────────────────────
144
158
 
145
- const hd = Buffer.alloc(COFF_TOTAL_SZ);
159
+ const hd = new Uint8Array(COFF_TOTAL_SZ);
160
+ const hddv = new DataView(hd.buffer);
146
161
  const machine = arch === 'x64' ? 0x8664 : 0xaa64;
147
162
  const ts = Math.floor(Date.now() / 1000);
148
163
 
149
164
  // CoffHeader @ 0
150
- hd.writeUInt16LE(machine, 0);
151
- hd.writeUInt16LE(2, 2); // numberOfSections
152
- hd.writeUInt32LE(ts, 4); // timeDateStamp
153
- hd.writeUInt32LE(COFF_OFFSETOF_RDATA, 8); // pointerToSymbolTable
154
- hd.writeUInt32LE(symbols.length + 5, 12); // numberOfSymbols (5 built-in + N exports)
165
+ hddv.setUint16(0, machine, true);
166
+ hddv.setUint16(2, 2, true); // numberOfSections
167
+ hddv.setUint32(4, ts, true); // timeDateStamp
168
+ hddv.setUint32(8, COFF_OFFSETOF_RDATA, true); // pointerToSymbolTable
169
+ hddv.setUint32(12, symbols.length + 5, true); // numberOfSymbols (5 built-in + N exports)
155
170
  // sizeOfOptionalHeader=0, flags=0 (zeroed)
156
171
 
157
172
  // CoffSection[0]: .drectve @ 20
158
173
  const drectvePtr = COFF_TOTAL_SZ + symd.length + tsd.length;
159
174
  setStr(hd, COFF_HDR_SZ, '.drectve', 8);
160
- hd.writeUInt32LE(tsed.length, COFF_HDR_SZ + 16); // sizeOfRawData
161
- hd.writeUInt32LE(drectvePtr, COFF_HDR_SZ + 20); // pointerToRawData
162
- hd.writeUInt32LE(0x00100a00, COFF_HDR_SZ + 36); // flags
175
+ hddv.setUint32(COFF_HDR_SZ + 16, tsed.length, true); // sizeOfRawData
176
+ hddv.setUint32(COFF_HDR_SZ + 20, drectvePtr, true); // pointerToRawData
177
+ hddv.setUint32(COFF_HDR_SZ + 36, 0x00100a00, true); // flags
163
178
 
164
179
  // CoffSection[1]: .rdata @ 60
165
180
  const rdataPtr = al(COFF_TOTAL_SZ + symd.length + tsd.length + tsed.length, 8);
166
181
  setStr(hd, COFF_HDR_SZ + COFF_SECT_SZ, '.rdata', 8);
167
- hd.writeUInt32LE(dsd.length, COFF_HDR_SZ + COFF_SECT_SZ + 16);
168
- hd.writeUInt32LE(rdataPtr, COFF_HDR_SZ + COFF_SECT_SZ + 20);
169
- hd.writeUInt32LE(0x40300040, COFF_HDR_SZ + COFF_SECT_SZ + 36);
182
+ hddv.setUint32(COFF_HDR_SZ + COFF_SECT_SZ + 16, dsd.length, true);
183
+ hddv.setUint32(COFF_HDR_SZ + COFF_SECT_SZ + 20, rdataPtr, true);
184
+ hddv.setUint32(COFF_HDR_SZ + COFF_SECT_SZ + 36, 0x40300040, true);
170
185
 
171
186
  // CoffSymbol: .rdata section symbol @ 100
172
187
  setStr(hd, 100, '.rdata', 8);
173
- hd.writeInt16LE(2, 100 + 12); // sectionNumber
174
- hd.writeUInt8(0x3, 100 + 16); // storageClass: IMAGE_SYM_CLASS_STATIC
175
- hd.writeUInt8(1, 100 + 17); // numberOfAuxSymbols
188
+ hddv.setInt16(100 + 12, 2, true); // sectionNumber
189
+ hd[100 + 16] = 0x3; // storageClass: IMAGE_SYM_CLASS_STATIC
190
+ hd[100 + 17] = 1; // numberOfAuxSymbols
176
191
 
177
192
  // CoffAuxSymbol for .rdata @ 118
178
- hd.writeUInt32LE(dsd.length, 118 + 0); // length
179
- hd.writeUInt16LE(2, 118 + 12); // number (= section index)
193
+ hddv.setUint32(118 + 0, dsd.length, true); // length
194
+ hddv.setUint16(118 + 12, 2, true); // number (= section index)
180
195
 
181
196
  // CoffSymbol: .drectve section symbol @ 136
182
197
  setStr(hd, 136, '.drectve', 8);
183
- hd.writeInt16LE(1, 136 + 12);
184
- hd.writeUInt8(0x3, 136 + 16);
185
- hd.writeUInt8(1, 136 + 17);
198
+ hddv.setInt16(136 + 12, 1, true);
199
+ hd[136 + 16] = 0x3;
200
+ hd[136 + 17] = 1;
186
201
 
187
202
  // CoffAuxSymbol for .drectve @ 154
188
- hd.writeUInt32LE(tsed.length, 154 + 0);
189
- hd.writeUInt16LE(1, 154 + 12);
203
+ hddv.setUint32(154 + 0, tsed.length, true);
204
+ hddv.setUint16(154 + 12, 1, true);
190
205
 
191
206
  // CoffSymbol: @feat.00 @ 172
192
207
  setStr(hd, 172, '@feat.00', 8);
193
- hd.writeInt16LE(-1, 172 + 12); // IMAGE_SYM_ABSOLUTE
194
- hd.writeUInt8(0x3, 172 + 16);
208
+ hddv.setInt16(172 + 12, -1, true); // IMAGE_SYM_ABSOLUTE
209
+ hd[172 + 16] = 0x3;
195
210
 
196
211
  // Pad tsed to 8-byte boundary so .rdata starts aligned
197
212
  const pad = rdataPtr - (COFF_TOTAL_SZ + symd.length + tsd.length + tsed.length);
198
- const tsedFinal = pad > 0 ? Buffer.concat([tsed, Buffer.alloc(pad)]) : tsed;
213
+ const tsedFinal = pad > 0 ? concat([tsed, new Uint8Array(pad)]) : tsed;
199
214
 
200
- return Buffer.concat([hd, symd, tsd, tsedFinal, dsd]);
215
+ return concat([hd, symd, tsd, tsedFinal, dsd]);
201
216
  }
202
217
 
203
218
  // ═══════════════════════════════════════════════════════════════════════════════
@@ -230,22 +245,25 @@ const MMO = 264; // mach_minimun_os_command
230
245
  const MSYM = 288; // mach_symtab_command
231
246
  const MDYS = 312; // mach_symtab_info (LC_DYSYMTAB)
232
247
 
233
- function doObjectMacOS(symbols: ObjSymbol[], arch: TargetArch): Buffer {
248
+ function doObjectMacOS(symbols: ObjSymbol[], arch: TargetArch): Uint8Array {
234
249
  let dataSz = 0, strTabSz = 1, symTabSz = 0;
235
250
 
236
251
  for (const { name, obj } of symbols) {
237
- if (obj instanceof Uint8Array) dataSz += al(obj.length, 16);
238
- else if (typeof obj === 'string') dataSz += al(obj.length, 16); // raw bytes, no null
239
- else if (typeof obj === 'number') dataSz += al(8, 16); // = 16
252
+ if (obj instanceof Uint8Array) dataSz += al(obj.length, 16);
253
+ else if (typeof obj === 'string') dataSz += al(obj.length, 16); // raw bytes, no null
254
+ else if (typeof obj === 'number') dataSz += al(8, 16); // = 16
240
255
  else throw new Error('Invalid symbol type');
241
256
  strTabSz += name.length + 2; // '_' + name + '\0'
242
257
  symTabSz += 16; // sizeof(mach_sym_entry)
243
258
  }
244
259
  strTabSz = al(strTabSz, 8);
245
260
 
246
- const dt = Buffer.alloc(dataSz); // data section
247
- const nt = Buffer.alloc(strTabSz); // string table (first byte is '\0' by alloc)
248
- const nti = Buffer.alloc(symTabSz); // symbol entries
261
+ const dt = new Uint8Array(dataSz); // data section
262
+ const nt = new Uint8Array(strTabSz); // string table (first byte is '\0' by alloc)
263
+ const nti = new Uint8Array(symTabSz); // symbol entries
264
+
265
+ const dtdv = new DataView(dt.buffer);
266
+ const ntidv = new DataView(nti.buffer);
249
267
 
250
268
  let dataOff = 0, strOff = 1;
251
269
 
@@ -257,88 +275,89 @@ function doObjectMacOS(symbols: ObjSymbol[], arch: TargetArch): Buffer {
257
275
  dt.set(obj, dataOff);
258
276
  dataOff += al(obj.length, 16);
259
277
  } else if (typeof obj === 'string') {
260
- dt.write(obj, dataOff, 'ascii');
278
+ dt.set(enc.encode(obj), dataOff);
261
279
  dataOff += al(obj.length, 16);
262
280
  } else if (typeof obj === 'number') {
263
- dt.writeDoubleLE(obj, dataOff);
281
+ dtdv.setFloat64(dataOff, obj, true);
264
282
  dataOff += al(8, 16);
265
283
  }
266
284
 
267
- nt.write('_' + name, strOff, 'ascii'); // null terminator from Buffer.alloc
285
+ nt.set(enc.encode('_' + name), strOff); // null terminator from Uint8Array zero-fill
268
286
 
269
287
  // mach_sym_entry @ k*16
270
288
  const e = k * 16;
271
- nti.writeUInt32LE(strOff, e + 0); // strx
272
- nti.writeUInt8(0xf, e + 4); // type: N_SECT | N_EXT
273
- nti.writeUInt8(2, e + 5); // sect: 2 = __const
274
- nti.writeUInt16LE(0, e + 6); // desc
275
- writeU64(nti, e + 8, valueInSection); // value = offset within section
289
+ ntidv.setUint32(e + 0, strOff, true); // strx
290
+ nti[e + 4] = 0xf; // type: N_SECT | N_EXT
291
+ nti[e + 5] = 2; // sect: 2 = __const
292
+ ntidv.setUint16(e + 6, 0, true); // desc
293
+ writeU64(ntidv, e + 8, valueInSection); // value = offset within section
276
294
 
277
295
  strOff += name.length + 2;
278
296
  }
279
297
 
280
- const hd = Buffer.alloc(MACH_HDR_SZ);
298
+ const hd = new Uint8Array(MACH_HDR_SZ);
299
+ const hddv = new DataView(hd.buffer);
281
300
 
282
301
  // mach_header_64
283
- hd.writeUInt32LE(0xfeedfacf, MH + 0); // MH_MAGIC_64
284
- hd.writeUInt32LE(arch === 'x64' ? 0x1000007 : 0x100000c, MH + 4); // cputype
285
- hd.writeUInt32LE(arch === 'x64' ? 0x3 : 0x0, MH + 8); // cpusubtype
286
- hd.writeUInt32LE(0x1, MH + 12); // filetype: MH_OBJECT
287
- hd.writeUInt32LE(4, MH + 16); // ncmds: 4 load commands
288
- hd.writeUInt32LE(0x168, MH + 20); // sizeofcmds = 0xE8+0x18+0x18+0x50 = 360
289
- hd.writeUInt32LE(0x200, MH + 24); // flags: MH_SUBSECTIONS_VIA_SYMBOLS
302
+ hddv.setUint32(MH + 0, 0xfeedfacf, true); // MH_MAGIC_64
303
+ hddv.setUint32(MH + 4, arch === 'x64' ? 0x1000007 : 0x100000c, true); // cputype
304
+ hddv.setUint32(MH + 8, arch === 'x64' ? 0x3 : 0x0, true); // cpusubtype
305
+ hddv.setUint32(MH + 12, 0x1, true); // filetype: MH_OBJECT
306
+ hddv.setUint32(MH + 16, 4, true); // ncmds: 4 load commands
307
+ hddv.setUint32(MH + 20, 0x168, true); // sizeofcmds = 0xE8+0x18+0x18+0x50 = 360
308
+ hddv.setUint32(MH + 24, 0x200, true); // flags: MH_SUBSECTIONS_VIA_SYMBOLS
290
309
 
291
310
  // LC_SEGMENT_64 (cmd=0x19, cmdsize=0xE8 = 72 + 80×2)
292
- hd.writeUInt32LE(0x19, MSEG + 0);
293
- hd.writeUInt32LE(0xE8, MSEG + 4);
311
+ hddv.setUint32(MSEG + 0, 0x19, true);
312
+ hddv.setUint32(MSEG + 4, 0xE8, true);
294
313
  // segname[16]: all zeros = unnamed segment (correct for .o files)
295
- writeU64(hd, MSEG + 24, 0); // vmaddr
296
- writeU64(hd, MSEG + 32, dataSz); // vmsize
297
- writeU64(hd, MSEG + 40, MACH_HDR_SZ); // fileoff
298
- writeU64(hd, MSEG + 48, dataSz); // filesize
299
- hd.writeUInt32LE(0x7, MSEG + 56); // maxprot: PROT_READ|WRITE|EXEC
300
- hd.writeUInt32LE(0x7, MSEG + 60); // initprot
301
- hd.writeUInt32LE(2, MSEG + 64); // nsects
314
+ writeU64(hddv, MSEG + 24, 0); // vmaddr
315
+ writeU64(hddv, MSEG + 32, dataSz); // vmsize
316
+ writeU64(hddv, MSEG + 40, MACH_HDR_SZ); // fileoff
317
+ writeU64(hddv, MSEG + 48, dataSz); // filesize
318
+ hddv.setUint32(MSEG + 56, 0x7, true); // maxprot: PROT_READ|WRITE|EXEC
319
+ hddv.setUint32(MSEG + 60, 0x7, true); // initprot
320
+ hddv.setUint32(MSEG + 64, 2, true); // nsects
302
321
 
303
322
  // mach_section_64[0]: __text (empty — placeholder for the TEXT segment)
304
323
  setStr(hd, MS1 + 0, '__text', 16);
305
324
  setStr(hd, MS1 + 16, '__TEXT', 16);
306
325
  // addr=0, size=0 (zeroed)
307
- hd.writeUInt32LE(MACH_HDR_SZ, MS1 + 48); // offset
326
+ hddv.setUint32(MS1 + 48, MACH_HDR_SZ, true); // offset
308
327
  // align=0
309
- hd.writeUInt32LE(0x80000000, MS1 + 64); // flags: S_ATTR_PURE_INSTRUCTIONS
328
+ hddv.setUint32(MS1 + 64, 0x80000000, true); // flags: S_ATTR_PURE_INSTRUCTIONS
310
329
 
311
330
  // mach_section_64[1]: __const (actual exported data)
312
331
  setStr(hd, MS2 + 0, '__const', 16);
313
332
  setStr(hd, MS2 + 16, '__TEXT', 16);
314
333
  // addr=0 (zeroed)
315
- writeU64(hd, MS2 + 40, dataSz); // size
316
- hd.writeUInt32LE(MACH_HDR_SZ, MS2 + 48); // offset
317
- hd.writeUInt32LE(0x02, MS2 + 52); // align: 2^2 = 4 bytes
334
+ writeU64(hddv, MS2 + 40, dataSz); // size
335
+ hddv.setUint32(MS2 + 48, MACH_HDR_SZ, true); // offset
336
+ hddv.setUint32(MS2 + 52, 0x02, true); // align: 2^2 = 4 bytes
318
337
 
319
338
  // LC_BUILD_VERSION (cmd=0x32)
320
- hd.writeUInt32LE(0x32, MMO + 0);
321
- hd.writeUInt32LE(0x18, MMO + 4);
322
- hd.writeUInt32LE(0x1, MMO + 8); // platform: PLATFORM_MACOS
323
- hd.writeUInt32LE(0xa0900, MMO + 12); // minos: 10.9.0
324
- hd.writeUInt32LE(0xa0900, MMO + 16); // sdk: 10.9.0
339
+ hddv.setUint32(MMO + 0, 0x32, true);
340
+ hddv.setUint32(MMO + 4, 0x18, true);
341
+ hddv.setUint32(MMO + 8, 0x1, true); // platform: PLATFORM_MACOS
342
+ hddv.setUint32(MMO + 12, 0xa0900, true); // minos: 10.9.0
343
+ hddv.setUint32(MMO + 16, 0xa0900, true); // sdk: 10.9.0
325
344
 
326
345
  // LC_SYMTAB (cmd=0x2)
327
- hd.writeUInt32LE(0x2, MSYM + 0);
328
- hd.writeUInt32LE(0x18, MSYM + 4);
329
- hd.writeUInt32LE(MACH_HDR_SZ + dataSz, MSYM + 8); // symoff
330
- hd.writeUInt32LE(symbols.length, MSYM + 12); // nsyms
331
- hd.writeUInt32LE(MACH_HDR_SZ + dataSz + symTabSz, MSYM + 16); // stroff
332
- hd.writeUInt32LE(strTabSz, MSYM + 20); // strsize
346
+ hddv.setUint32(MSYM + 0, 0x2, true);
347
+ hddv.setUint32(MSYM + 4, 0x18, true);
348
+ hddv.setUint32(MSYM + 8, MACH_HDR_SZ + dataSz, true); // symoff
349
+ hddv.setUint32(MSYM + 12, symbols.length, true); // nsyms
350
+ hddv.setUint32(MSYM + 16, MACH_HDR_SZ + dataSz + symTabSz, true); // stroff
351
+ hddv.setUint32(MSYM + 20, strTabSz, true); // strsize
333
352
 
334
353
  // LC_DYSYMTAB (cmd=0xb)
335
- hd.writeUInt32LE(0xb, MDYS + 0);
336
- hd.writeUInt32LE(0x50, MDYS + 4);
354
+ hddv.setUint32(MDYS + 0, 0xb, true);
355
+ hddv.setUint32(MDYS + 4, 0x50, true);
337
356
  // localoff=0, nlocals=0 (zeroed)
338
- hd.writeUInt32LE(symbols.length, MDYS + 20); // nextdef
339
- hd.writeUInt32LE(symbols.length, MDYS + 24); // undefoff
357
+ hddv.setUint32(MDYS + 20, symbols.length, true); // nextdef
358
+ hddv.setUint32(MDYS + 24, symbols.length, true); // undefoff
340
359
 
341
- return Buffer.concat([hd, dt, nti, nt]);
360
+ return concat([hd, dt, nti, nt]);
342
361
  }
343
362
 
344
363
  // ═══════════════════════════════════════════════════════════════════════════════
@@ -377,7 +396,7 @@ const EY = { NAME:0, INFO:4, OTHER:5, SECTIDX:6, VALUE:8, SIZE:16 };
377
396
 
378
397
  const sectOfs = (idx: number): number => ELF_HDR_SZ + idx * ELF_SECT_SZ;
379
398
 
380
- function doObjectLinux(symbols: ObjSymbol[], arch: TargetArch): Buffer {
399
+ function doObjectLinux(symbols: ObjSymbol[], arch: TargetArch): Uint8Array {
381
400
  const SH_NAMES = '\0.symtab\0.strtab\0.rodata\0.note.GNU-stack\0';
382
401
  // idx: 0 1 9 17 25
383
402
  const I_SYMTAB = 1, I_STRTAB = 9, I_RODATA = 17, I_NOTE = 25;
@@ -386,18 +405,21 @@ function doObjectLinux(symbols: ObjSymbol[], arch: TargetArch): Buffer {
386
405
 
387
406
  for (const { name, obj } of symbols) {
388
407
  strTabSz += name.length + 1;
389
- if (obj instanceof Uint8Array) dataSz += al(obj.length, 8);
390
- else if (typeof obj === 'string') dataSz += al(obj.length + 1, 8);
391
- else if (typeof obj === 'number') dataSz += 8;
408
+ if (obj instanceof Uint8Array) dataSz += al(obj.length, 8);
409
+ else if (typeof obj === 'string') dataSz += al(obj.length + 1, 8);
410
+ else if (typeof obj === 'number') dataSz += 8;
392
411
  else throw new Error('Invalid symbol type');
393
412
  }
394
413
 
395
414
  // Symbol table: one null entry (index 0) + one per export
396
- const symd = Buffer.alloc(al(ELF_SYM_SZ * (symbols.length + 1), 16));
397
- const ts = Buffer.alloc(al(strTabSz, 16));
398
- const d = Buffer.alloc(al(dataSz, 16));
415
+ const symd = new Uint8Array(al(ELF_SYM_SZ * (symbols.length + 1), 16));
416
+ const ts = new Uint8Array(al(strTabSz, 16));
417
+ const d = new Uint8Array(al(dataSz, 16));
418
+
419
+ const symdv = new DataView(symd.buffer);
420
+ const ddv = new DataView(d.buffer);
399
421
 
400
- ts.write(SH_NAMES, 0, 'ascii');
422
+ ts.set(enc.encode(SH_NAMES), 0);
401
423
 
402
424
  let strOff = SH_NAMES.length, dataOff = 0;
403
425
 
@@ -405,52 +427,53 @@ function doObjectLinux(symbols: ObjSymbol[], arch: TargetArch): Buffer {
405
427
  const { name, obj } = symbols[k]!;
406
428
  const sb = (k + 1) * ELF_SYM_SZ; // skip null symbol at index 0
407
429
 
408
- symd.writeUInt32LE(strOff, sb + EY.NAME);
409
- symd.writeUInt8(0x11, sb + EY.INFO); // STB_GLOBAL|STT_OBJECT = (1<<4)|1
410
- symd.writeUInt8(0, sb + EY.OTHER);
411
- symd.writeUInt16LE(3, sb + EY.SECTIDX); // .rodata = section 3
412
- writeU64(symd, sb + EY.VALUE, dataOff);
430
+ symdv.setUint32(sb + EY.NAME, strOff, true);
431
+ symd[sb + EY.INFO] = 0x11; // STB_GLOBAL|STT_OBJECT = (1<<4)|1
432
+ symd[sb + EY.OTHER] = 0;
433
+ symdv.setUint16(sb + EY.SECTIDX, 3, true); // .rodata = section 3
434
+ writeU64(symdv, sb + EY.VALUE, dataOff);
413
435
 
414
- ts.write(name, strOff, 'ascii');
436
+ ts.set(enc.encode(name), strOff);
415
437
  strOff += name.length + 1;
416
438
 
417
439
  if (obj instanceof Uint8Array) {
418
440
  d.set(obj, dataOff);
419
- writeU64(symd, sb + EY.SIZE, obj.length);
441
+ writeU64(symdv, sb + EY.SIZE, obj.length);
420
442
  dataOff += al(obj.length, 8);
421
443
  } else if (typeof obj === 'string') {
422
- d.write(obj, dataOff, 'ascii');
423
- writeU64(symd, sb + EY.SIZE, obj.length + 1);
444
+ d.set(enc.encode(obj), dataOff);
445
+ writeU64(symdv, sb + EY.SIZE, obj.length + 1);
424
446
  dataOff += al(obj.length + 1, 8);
425
447
  } else if (typeof obj === 'number') {
426
- d.writeDoubleLE(obj, dataOff);
427
- writeU64(symd, sb + EY.SIZE, 8);
448
+ ddv.setFloat64(dataOff, obj, true);
449
+ writeU64(symdv, sb + EY.SIZE, 8);
428
450
  dataOff += 8;
429
451
  }
430
452
  }
431
453
 
432
454
  // ── ELF header + section headers ───────────────────────────────────────────
433
455
 
434
- const hd = Buffer.alloc(ELF_STRUCT_SZ);
435
- const mach = arch === 'x64' ? 0x3e : 0xb7;
456
+ const hd = new Uint8Array(ELF_STRUCT_SZ);
457
+ const hddv = new DataView(hd.buffer);
458
+ const mach = arch === 'x64' ? 0x3e : 0xb7;
436
459
 
437
460
  // ELF64Header @ 0
438
- hd.write('\x7fELF', 0, 'ascii');
439
- hd.writeUInt8(2, 4); // EI_CLASS: ELFCLASS64
440
- hd.writeUInt8(1, 5); // EI_DATA: ELFDATA2LSB
441
- hd.writeUInt8(1, 6); // EI_VERSION: EV_CURRENT
461
+ hd.set([0x7f, 0x45, 0x4c, 0x46], 0); // \x7fELF
462
+ hd[4] = 2; // EI_CLASS: ELFCLASS64
463
+ hd[5] = 1; // EI_DATA: ELFDATA2LSB
464
+ hd[6] = 1; // EI_VERSION: EV_CURRENT
442
465
  // osabi=0, abiversion=0, epad=0
443
- hd.writeUInt16LE(1, 16); // e_type: ET_REL
444
- hd.writeUInt16LE(mach, 18); // e_machine
445
- hd.writeUInt32LE(1, 20); // e_version: EV_CURRENT
466
+ hddv.setUint16(16, 1, true); // e_type: ET_REL
467
+ hddv.setUint16(18, mach, true); // e_machine
468
+ hddv.setUint32(20, 1, true); // e_version: EV_CURRENT
446
469
  // e_entry=0, e_phoff=0 (zeroed)
447
- writeU64(hd, 40, ELF_HDR_SZ); // e_shoff: section headers right after hdr
470
+ writeU64(hddv, 40, ELF_HDR_SZ); // e_shoff: section headers right after hdr
448
471
  // e_flags=0 (zeroed)
449
- hd.writeUInt16LE(ELF_HDR_SZ, 52); // e_ehsize
472
+ hddv.setUint16(52, ELF_HDR_SZ, true); // e_ehsize
450
473
  // e_phentsize=0, e_phnum=0 (zeroed)
451
- hd.writeUInt16LE(ELF_SECT_SZ, 58); // e_shentsize
452
- hd.writeUInt16LE(6, 60); // e_shnum
453
- hd.writeUInt16LE(2, 62); // e_shstrndx: .strtab = section 2
474
+ hddv.setUint16(58, ELF_SECT_SZ, true); // e_shentsize
475
+ hddv.setUint16(60, 6, true); // e_shnum
476
+ hddv.setUint16(62, 2, true); // e_shstrndx: .strtab = section 2
454
477
 
455
478
  const symtabOfs = ELF_STRUCT_SZ;
456
479
  const strtabOfs = ELF_STRUCT_SZ + symd.length;
@@ -461,38 +484,38 @@ function doObjectLinux(symbols: ObjSymbol[], arch: TargetArch): Buffer {
461
484
 
462
485
  // Section[1]: .symtab
463
486
  const s1 = sectOfs(1);
464
- hd.writeUInt32LE(I_SYMTAB, s1 + ES.NAME);
465
- hd.writeUInt32LE(2, s1 + ES.TYPE); // SHT_SYMTAB
466
- writeU64(hd, s1 + ES.OFS, symtabOfs);
467
- writeU64(hd, s1 + ES.SIZE, symd.length);
468
- hd.writeUInt32LE(2, s1 + ES.LINK); // associated .strtab = section 2
469
- hd.writeUInt32LE(1, s1 + ES.INFO); // first global symbol index
470
- writeU64(hd, s1 + ES.ALIGN, 8);
471
- writeU64(hd, s1 + ES.ENTSZ, ELF_SYM_SZ);
487
+ hddv.setUint32(s1 + ES.NAME, I_SYMTAB, true);
488
+ hddv.setUint32(s1 + ES.TYPE, 2, true); // SHT_SYMTAB
489
+ writeU64(hddv, s1 + ES.OFS, symtabOfs);
490
+ writeU64(hddv, s1 + ES.SIZE, symd.length);
491
+ hddv.setUint32(s1 + ES.LINK, 2, true); // associated .strtab = section 2
492
+ hddv.setUint32(s1 + ES.INFO, 1, true); // first global symbol index
493
+ writeU64(hddv, s1 + ES.ALIGN, 8);
494
+ writeU64(hddv, s1 + ES.ENTSZ, ELF_SYM_SZ);
472
495
 
473
496
  // Section[2]: .strtab
474
497
  const s2 = sectOfs(2);
475
- hd.writeUInt32LE(I_STRTAB, s2 + ES.NAME);
476
- hd.writeUInt32LE(3, s2 + ES.TYPE); // SHT_STRTAB
477
- writeU64(hd, s2 + ES.OFS, strtabOfs);
478
- writeU64(hd, s2 + ES.SIZE, ts.length);
498
+ hddv.setUint32(s2 + ES.NAME, I_STRTAB, true);
499
+ hddv.setUint32(s2 + ES.TYPE, 3, true); // SHT_STRTAB
500
+ writeU64(hddv, s2 + ES.OFS, strtabOfs);
501
+ writeU64(hddv, s2 + ES.SIZE, ts.length);
479
502
 
480
503
  // Section[3]: .rodata
481
504
  const s3 = sectOfs(3);
482
- hd.writeUInt32LE(I_RODATA, s3 + ES.NAME);
483
- hd.writeUInt32LE(1, s3 + ES.TYPE); // SHT_PROGBITS
484
- writeU64(hd, s3 + ES.FLAGS, 2); // SHF_ALLOC
485
- writeU64(hd, s3 + ES.OFS, rodataOfs);
486
- writeU64(hd, s3 + ES.SIZE, d.length);
505
+ hddv.setUint32(s3 + ES.NAME, I_RODATA, true);
506
+ hddv.setUint32(s3 + ES.TYPE, 1, true); // SHT_PROGBITS
507
+ writeU64(hddv, s3 + ES.FLAGS, 2); // SHF_ALLOC
508
+ writeU64(hddv, s3 + ES.OFS, rodataOfs);
509
+ writeU64(hddv, s3 + ES.SIZE, d.length);
487
510
 
488
511
  // Section[4]: .note.GNU-stack (empty; signals non-executable stack to linker)
489
512
  const s4 = sectOfs(4);
490
- hd.writeUInt32LE(I_NOTE, s4 + ES.NAME);
491
- hd.writeUInt32LE(1, s4 + ES.TYPE); // SHT_PROGBITS
492
- writeU64(hd, s4 + ES.OFS, noteOfs);
513
+ hddv.setUint32(s4 + ES.NAME, I_NOTE, true);
514
+ hddv.setUint32(s4 + ES.TYPE, 1, true); // SHT_PROGBITS
515
+ writeU64(hddv, s4 + ES.OFS, noteOfs);
493
516
  // size=0, flags=0 (zeroed)
494
517
 
495
- return Buffer.concat([hd, symd, ts, d]);
518
+ return concat([hd, symd, ts, d]);
496
519
  }
497
520
 
498
521
  // ═══════════════════════════════════════════════════════════════════════════════
@@ -503,7 +526,7 @@ function dispatch(
503
526
  symbols: ObjSymbol[],
504
527
  arch: TargetArch = hostArch(),
505
528
  platform: TargetPlatform = hostPlatform(),
506
- ): Buffer {
529
+ ): Uint8Array {
507
530
  switch (platform) {
508
531
  case 'win32': return doObjectWindows(symbols, arch);
509
532
  case 'macos': return doObjectMacOS(symbols, arch);
@@ -518,7 +541,7 @@ export function encodeObject(
518
541
  obj: SymbolValue,
519
542
  arch?: TargetArch,
520
543
  platform?: TargetPlatform,
521
- ): Buffer {
544
+ ): Uint8Array {
522
545
  return dispatch([{ name, obj }], arch, platform);
523
546
  }
524
547
 
@@ -527,6 +550,6 @@ export function encodeSymbols(
527
550
  symbols: ObjSymbol[],
528
551
  arch?: TargetArch,
529
552
  platform?: TargetPlatform,
530
- ): Buffer {
553
+ ): Uint8Array {
531
554
  return dispatch(symbols, arch, platform);
532
555
  }
package/package.json CHANGED
@@ -1,10 +1,14 @@
1
1
  {
2
2
  "name": "@retrovm/nobj",
3
- "version": "0.1.2",
3
+ "version": "0.1.4",
4
4
  "description": "Generate native linkable object files (COFF, Mach-O, ELF64) from TypeScript/Bun — zero native dependencies",
5
5
  "license": "MIT",
6
6
  "author": "Juan Carlos González Amestoy",
7
7
  "keywords": ["native", "object", "coff", "macho", "elf", "linker", "bun", "embed"],
8
+ "repository": {
9
+ "type": "git",
10
+ "url": "https://github.com/jcgamestoy/nobj"
11
+ },
8
12
  "exports": {
9
13
  ".": "./nobj.ts"
10
14
  },