I'm trying to compile a golang project to wasm, the compiler complains something like non-pc-relative relocation address for github.com/xxx/yyy/zzz.SomeSymbol is too big: 0x1079a0000.
Then I try to read the compiler code and found that the golang compiler will left shift the address with 16 bits so that there are only 16 bits symbol address (65536 symbols) can be used with wasm32: https://github.com/golang/go/blob/dev.boringcrypto.go1.16/src/cmd/link/internal/wasm/asm.go#L74
func assignAddress(ldr *loader.Loader, sect *sym.Section, n int, s loader.Sym, va uint64, isTramp bool) (*sym.Section, int, uint64) {
// WebAssembly functions do not live in the same address space as the linear memory.
// Instead, WebAssembly automatically assigns indices. Imported functions (section "import")
// have indices 0 to n. They are followed by native functions (sections "function" and "code")
// with indices n+1 and following.
//
// The following rules describe how wasm handles function indices and addresses:
// PC_F = funcValueOffset + WebAssembly function index (not including the imports)
// s.Value = PC = PC_F<<16 + PC_B
//
// The funcValueOffset is necessary to avoid conflicts with expectations
// that the Go runtime has about function addresses.
// The field "s.Value" corresponds to the concept of PC at runtime.
// However, there is no PC register, only PC_F and PC_B. PC_F denotes the function,
// PC_B the resume point inside of that function. The entry of the function has PC_B = 0.
ldr.SetSymSect(s, sect)
ldr.SetSymValue(s, int64(funcValueOffset+va/ld.MINFUNC)<<16) // va starts at zero
va += uint64(ld.MINFUNC)
return sect, n, va
}
Is there any special reason that the compiler must do so?
Related
I have a structure in C and I called that structure in my go program. If that structure throws any error it terminates my go program like below
orderbook.h
-------------
#ifndef _ORDERBOOK_H
#define _ORDERBOOK_H
typedef struct order order;
struct order {
int tradeid;
int side;
int symbol;
double amount;
double price;
};
orderbook.c
--------------
include "orderbook.h"
order* order_place(char *side,double amount,double price,char symbol[19])
{
struct order *tradeorder= calloc(1000000,sizeof(struct order));//Initlize the structure
//My internal code which place an order
clob_ord_t o=unxs_order(c, (clob_ord_t){CLOB_TYPE_LMT,parsed_side, amount, .lmt =price, .usr = (uintptr_t)out},NANPX);
if (o.qty.dis + o.qty.hid > 0.dd) {
/* put remainder of order into book */
i = clob_add(c, o);
//printf("orderid..%lu\n", i.usr);
printf("orderid..%s\n", i.usr);
insertMap(hashTable, i.usr, i);
// printMap(hashTable);
flag=true;
tradeorder[0].orderstatus=1;
tradeorder[0].orderid=offerid;
tradeorder[0].side=sid;
tradeorder[0].symbol=atoi(symbol);
tradeorder[0].amount=(double)o.qty.dis;
tradeorder[0].price=price;
}
return tradeorder; //return the structure
}
main.go
---------
o:=C.order_place(C.CString("ASK"),C.double(12.0),C.double(1.0),C.CString("1")) //this line may get an exception If some wrong parameter to pass otherwise returns correct value
If I put correct parameter to order_pace function from go there is no issue, If I pass some incorrect parameter then In get an exception an it terminates the go server. Now I need to handle that exception so that my server remain running irrespective of an exception.
You can't catch the fatal fault, and it isn't safe to continue after your C code throws a fault (unlike Go). The running program is in an undefined potentially dangerous state. The safest thing to do is shutdown the program and/or let it crash.
You must check for errors within C.order_place and return an error on failure. Eg, return NULL.
A few other recommendations:
Allocate struct order via Go to rely on the garbage collector to simplify memory management.
var order C.struct_order
C.order_place(&order, side, ...)
Always free strings allocated via C.CString once they are no longer needed.
cstr := C.CString("test")
C.free(unsafe.Pointer(cstr))
Depending on your platform, you can simplify debugging with improved stack traces by importing cgosymbolizer. This adds support for C stack traces.
import _ "github.com/ianlancetaylor/cgosymbolizer"
You probably should use char *symbol instead of char symbol[19] in your example since C.CString returns a pointer to an arbitrarily long C string, not a pointer to an array of 19 chars.
In the source code's comments of JCublas2.cublasSdot, it's commented that the 'result' parameter can be a 'host or device pointer'.
public static int cublasSdot(
cublasHandle handle,
int n,
Pointer x,
int incx,
Pointer y,
int incy,
Pointer result)/** host or device pointer */
{
return checkResult(cublasSdotNative(handle, n, x, incx, y, incy, result));
}
However, I can use only a host pointer like Pointer.to(fs) with float[] fs ={0}. If I use a device pointer like 'CUdeviceptr devicePtr = new CUdeviceptr(); JCudaDriver.cuMemAlloc(devicePtr, 100 * Sizeof.FLOAT);', the program crashes with console messages like:
#
# A fatal error has been detected by the Java Runtime Environment:
#
# EXCEPTION_ACCESS_VIOLATION (0xc0000005) at pc=0x000007fed93af2a3, pid=9376, tid=0x0000000000003a7c
# .....
Minimization of data transfer between host and device saves time. How to use device Pointer as the 'result' argument for this method, as well as other JCuda methods with result Pointer commented with /** host or device pointer **/?
CUBLAS can write the results of certain computations (like the dot product) either to host or to device memory. The target memory type has to be set explicitly, using cublasSetPointerMode.
An example of how this can be used is shown in the JCublas2PointerModes sample.
It once writes the result of the dot product computation to host memory (which is also the default, when no pointer mode is set explicitly):
// Set the pointer mode to HOST
cublasSetPointerMode(handle, CUBLAS_POINTER_MODE_HOST);
// Prepare the pointer for the result in HOST memory
float hostResult[] = { -1.0f };
Pointer hostResultPointer = Pointer.to(hostResult);
// Execute the 'dot' function
cublasSdot(handle, n, deviceData, 1, deviceData, 1, hostResultPointer);
And then changes the pointer mode and calls the function again, this time writing the result to device memory:
cublasSetPointerMode(handle, CUBLAS_POINTER_MODE_DEVICE);
// Prepare the pointer for the result in DEVICE memory
Pointer deviceResultPointer = new Pointer();
cudaMalloc(deviceResultPointer, Sizeof.FLOAT);
// Execute the 'dot' function
cublasSdot(handle, n, deviceData, 1, deviceData, 1, deviceResultPointer);
Global Offset Table (GOT): Is used for relocation of ELF symbols (implemented GCC), It helps in sharing of same binary without any specific linking for each process. Thus reduces copies of same binary image in the memory.
My question is, is there any way to disable R_386_GOT32,R_386_GOTOFF type relocation entries in relocatable ELF image? I mean, can I force GCC to use R_386_PC32 or R_386_32 type relocation instead of GOT type relocation?
If not, could you explain the way of implementing GOT? I am writing a dynamic linking and loading library for ELF.
Edit:
Reference Links
https://docs.oracle.com/cd/E23824_01/html/819-0690/chapter6-74186.html
http://man7.org/linux/man-pages/man8/ld.so.8.html
http://wiki.osdev.org/ELF
Finally I cracked it!
No, It is not possible to restrict GCC to output with non-GOT type relocation.
Now how to resolve GOT type relocation?
GOT is of fixed 128KB memory chunk (It works on principle of copy on write) allocated by dynamic linker which contains entries for relocation.
Dynamic Linker allocates GOT only if any type of (listed below) GOT relocation exist in ELF binary.
R_386_GOTOFF (== 0x9)
This relocation type computes the difference between a symbol's value and the address of the global offset table. It also instructs the link-editor to create the global offset table.
R_386_GOTPC (== 0xA)
This relocation type resembles R_386_PC32, except it uses the address of the global offset table in its calculation.
How to implement them?
Note: Following code-snippet belongs to Atom OS source code which protected by closed source license. But I (Atom Developer) hereby declare this code snippet free to use :)
uint GOT = Heap.kmalloc(1024 * 128); // 128 KB
...
private static void Relocate(Elf_Header* aHeader, Elf_Shdr* aShdr, uint GOT)
{
uint BaseAddress = (uint)aHeader;
Elf32_Rel* Reloc = (Elf32_Rel*)aShdr->sh_addr;
Elf_Shdr* TargetSection = (Elf_Shdr*)(BaseAddress + aHeader->e_shoff) + aShdr->sh_info;
uint RelocCount = aShdr->sh_size / aShdr->sh_entsize;
uint SymIdx, SymVal, RelocType;
for (int i = 0; i < RelocCount; i++, Reloc++)
{
SymVal = 0;
SymIdx = (Reloc->r_info >> 8);
RelocType = Reloc->r_info & 0xFF;
if (SymIdx != SHN_UNDEF)
{
if (RelocType == R_386_GOTPC)
SymVal = GOT;
else
SymVal = GetSymValue(aHeader, TargetSection->sh_link, SymIdx);
}
uint* add_ref = (uint*)(TargetSection->sh_addr + Reloc->r_offset);
switch(RelocType)
{
case R_386_32:
*add_ref = SymVal + *add_ref; // S + A
break;
case R_386_GOTOFF:
*add_ref = SymVal + *add_ref - GOT; // S + A - GOT
break;
case R_386_PLT32: // L + A - P
case R_386_PC32: // S + A - P
case R_386_GOTPC: // GOT + A - P
*add_ref = SymVal + *add_ref - (uint)add_ref;
break;
default:
throw new Exception("[ELF]: Unsupported Relocation type");
}
}
}
gcc -fno-plt -fno-pic will limit relocation types to R_386_PC32 and R_386_32 (or at least it worked in my case). Accepted answer is misleading in claiming it's not possible.
You can try to use gcc option: -fPIE or -fpie which could disable the GOT.
First off, I've read this question:
What's the right way to make a stack (or other dynamically resizable vector-like thing) in Rust?
The problem
The selected answer just tells the question asker to use the standard library instead of explaining the implementation, which is fine if my goal was to build something. Except I'm trying to learn about the implementation of a stack, while following a data structure textbook written for Java (Algorithms by Robert Sedgwick & Kevin Wayne), where they implement a stack via resizing an array (Page 136).
I'm in the process of implementing the resize method, and it turns out the size of the array needs to be a constant expression.
meta: are arrays in rust called slices?
use std::mem;
struct DynamicStack<T> {
length: uint,
internal: Box<[T]>,
}
impl<T> DynamicStack<T> {
fn new() -> DynamicStack<T> {
DynamicStack {
length: 0,
internal: box [],
}
}
fn resize(&mut self, new_size: uint) {
let mut temp: Box<[T, ..new_size]> = box unsafe { mem::uninitialized() };
// ^^ error: expected constant expr for array
// length: non-constant path in constant expr
// code for copying elements from self.internal
self.internal = temp;
}
}
For brevity the compiler error was this
.../src/lib.rs:51:23: 51:38 error: expected constant expr for array length: non-constant path in constant expr
.../src/lib.rs:51 let mut temp: Box<[T, ..new_size]> = box unsafe { mem::uninitialized() };
^~~~~~~~~~~~~~~
.../src/lib.rs:51:23: 51:38 error: expected constant expr for array length: non-constant path in constant expr
.../src/lib.rs:51 let mut temp: Box<[T, ..new_size]> = box unsafe { mem::uninitialized() };
^~~~~~~~~~~~~~~
The Question
Surely there is a way in rust to initialize an array with it's size determined at runtime (even if it's unsafe)? Could you also provide an explanation of what's going on in your answer?
Other attempts
I've considered it's probably possible to implement the stack in terms of
struct DynamicStack<T> {
length: uint,
internal: Box<Optional<T>>
}
But I don't want the overhead of matching optional value to remove the unsafe memory operations, but this still doesn't resolve the issue of unknown array sizes.
I also tried this (which doesn't even compile)
fn resize(&mut self, new_size: uint) {
let mut temp: Box<[T]> = box [];
let current_size = self.internal.len();
for i in range(0, current_size) {
temp[i] = self.internal[i];
}
for i in range(current_size, new_size) {
temp[i] = unsafe { mem::uninitialized() };
}
self.internal = temp;
}
And I got this compiler error
.../src/lib.rs:55:17: 55:21 error: cannot move out of dereference of `&mut`-pointer
.../src/lib.rs:55 temp[i] = self.internal[i];
^~~~
.../src/lib.rs:71:19: 71:30 error: cannot use `self.length` because it was mutably borrowed
.../src/lib.rs:71 self.resize(self.length * 2);
^~~~~~~~~~~
.../src/lib.rs:71:7: 71:11 note: borrow of `*self` occurs here
.../src/lib.rs:71 self.resize(self.length * 2);
^~~~
.../src/lib.rs:79:18: 79:22 error: cannot move out of dereference of `&mut`-pointer
.../src/lib.rs:79 let result = self.internal[self.length];
^~~~
.../src/lib.rs:79:9: 79:15 note: attempting to move value to here
.../src/lib.rs:79 let result = self.internal[self.length];
^~~~~~
.../src/lib.rs:79:9: 79:15 help: to prevent the move, use `ref result` or `ref mut result` to capture value by reference
.../src/lib.rs:79 let result = self.internal[self.length];
I also had a look at this, but it's been awhile since I've done any C/C++
How should you do pointer arithmetic in rust?
Surely there is a way in Rust to initialize an array with it's size determined at runtime?
No, Rust arrays are only able to be created with a size known at compile time. In fact, each tuple of type and size constitutes a new type! The Rust compiler uses that information to make optimizations.
Once you need a set of things determined at runtime, you have to add runtime checks to ensure that Rust's safety guarantees are always valid. For example, you can't access uninitialized memory (such as by walking off the beginning or end of a set of items).
If you truly want to go down this path, I expect that you are going to have to get your hands dirty with some direct memory allocation and unsafe code. In essence, you will be building a smaller version of Vec itself! To that end, you can check out the source of Vec.
At a high level, you will need to allocate chunks of memory big enough to hold N objects of some type. Then you can provide ways of accessing those elements, using pointer arithmetic under the hood. When you add more elements, you can allocate more space and move old values around. There are lots of nuanced things that may or may not come up, but it sounds like you are on the beginning of a fun journey!
Edit
Of course, you could choose to pretend that most of the methods of Vec don't even exist, and just use the ones that are analogs of Java's array. You'll still need to use Option to avoid uninitialized values though.
I wanted to use the Swift method CFSwapInt16BigToHost but I can't get it linking. I link against the CoreFoundation framework, but every time I get the following error :
Undefined symbols for architecture i386:
"__OSSwapInt16", referenced from:
Did I miss something ?
Yes, for some reason the CFSwap... functions cannot be used in a Swift program.
But since Xcode 6 beta 3, all integer types have little/bigEndian: constructors
and little/bigEndian properties.
From the UInt16 struct definition:
/// Creates an integer from its big-endian representation, changing the
/// byte order if necessary.
init(bigEndian value: UInt16)
/// Creates an integer from its little-endian representation, changing the
/// byte order if necessary.
init(littleEndian value: UInt16)
/// Returns the big-endian representation of the integer, changing the
/// byte order if necessary.
var bigEndian: UInt16 { get }
/// Returns the little-endian representation of the integer, changing the
/// byte order if necessary.
var littleEndian: UInt16 { get }
Example:
// Data buffer containing the number 1 in 16-bit, big-endian order:
var bytes : [UInt8] = [ 0x00, 0x01]
let data = NSData(bytes: &bytes, length: bytes.count)
// Read data buffer into integer variable:
var i16be : UInt16 = 0
data.getBytes(&i16be, length: sizeofValue(i16be))
println(i16be) // Output: 256
// Convert from big-endian to host byte-order:
let i16 = UInt16(bigEndian: i16be)
println(i16) // Output: 1
Update: As of Xcode 6.1.1, the CFSwap... functions are available in Swift, so
let i16 = CFSwapInt16BigToHost(bigEndian: i16be)
let i16 = UInt16(bigEndian: i16be)
both work, with identical results.
It looks like those are handled with a combination of macro's and inline functions so... I don't know why it wouldn't be already statically compiled into the CF version:
generally to solve this kind of dependency riddle you can just search for the naked function name without prefixed underscores, then figure out where it should be linked from
#define OSSwapInt16(x) __DARWIN_OSSwapInt16(x)
then
#define __DARWIN_OSSwapInt16(x) \
((__uint16_t)(__builtin_constant_p(x) ? __DARWIN_OSSwapConstInt16(x) : _OSSwapInt16(x)))
then
__DARWIN_OS_INLINE
__uint16_t
_OSSwapInt16(
__uint16_t _data
)
{
return ((__uint16_t)((_data << 8) | (_data >> 8)));
}
I know this isn't a real answer but it was too big for a comment,
I think you may need to find out if there is a problem with the way that swift imports the headers... like if for instance the macro's to import headers isn't correct in a swift setup.
As the other answers have pointed out, the __OSSwapInt16 swap method does not appear to be in the swift header of the CFByte framework. I think the swift like alternative would be:
var dataLength: UInt16 = 24
var swapped = UInt16(dataLength).byteSwapped