pkujhd / goloader

load and run golang code at runtime.
Apache License 2.0
506 stars 58 forks source link

the `addfuncdata` rewrite `0` to `^uint32(0)`, but ignoring the case where 0 represents a normal offset value. #79

Closed fumeboy closed 1 year ago

fumeboy commented 1 year ago

https://github.com/pkujhd/goloader/blob/09f36c84ac85502eb5df4670f1aa7472934ba03a/functab.1.18.go#L31

if the offset of the symbol happens to be exactly 0, it will erroneously turn it into 0xffffffff.

and the way to fix it is, when adding the funcdata offset to the Func.FuncData array (before executing the addfuncdata function), convert 0 to 0xffffffff.

eh-steve commented 1 year ago

Have you actually been able to hit a real case where the FuncData symbol offset is zero? In my fork I don't think it's possible because symbols are added in a deterministic order as read by the archive reader, and funcdata can never be the first symbol laid out by the compiler...

eh-steve commented 1 year ago

There are a couple of other tables where 0 is treated as an invalid offset so I've padded the start of the table:

https://github.com/eh-steve/goloader/blob/9fbc78a6d5210680c45d9d54dedbaf66c1314e42/ld.go#L98

fumeboy commented 1 year ago

Yes, goloader currently does not directly encounter this problem because it fills a 0x00 padding for noptrdata, so that the offset address of the symbol on this segment starts from 8 instead of 0.

linker.noptrdata = append(linker.noptrdata, make([]byte, IntSize)...)

If there is no such padding, then it is possible that the offset address of the symbol starts from 0. I guess this is also why funcdata uses -1 to represent vacancy instead of using 0.

eh-steve commented 1 year ago

So I don't think this is an issue...

pkujhd commented 1 year ago

Yes, goloader currently does not directly encounter this problem because it fills a 0x00 padding for noptrdata, so that the offset address of the symbol on this segment starts from 8 instead of 0.

linker.noptrdata = append(linker.noptrdata, make([]byte, IntSize)...)

If there is no such padding, then it is possible that the offset address of the symbol starts from 0. I guess this is also why funcdata uses -1 to represent vacancy instead of using 0.

golang compiler does not allocate memory for constant 0, so in noptrdata, 0 is filled into it first, it avoids funcdata's offset start with 0