Skip to content

Commit

Permalink
fix #93, fix fill findfuncbucket error
Browse files Browse the repository at this point in the history
  • Loading branch information
pkujhd committed Dec 2, 2023
1 parent e246461 commit 2fbc174
Showing 1 changed file with 21 additions and 13 deletions.
34 changes: 21 additions & 13 deletions ld.go
Original file line number Diff line number Diff line change
Expand Up @@ -446,22 +446,30 @@ func (linker *Linker) buildModule(codeModule *CodeModule, symbolMap map[string]u
}
module.ftab = append(module.ftab, initfunctab(module.maxpc, uintptr(len(module.pclntable)), module.text))

//see:^src/cmd/link/internal/ld/pcln.go findfunctab
// see:^src/cmd/link/internal/ld/pcln.go findfunctab
funcbucket := []findfuncbucket{}
for k, _func := range linker._funcs {
funcname := getfuncname(_func, module)
x := linker.symMap[funcname].Offset
b := x / pcbucketsize
i := x % pcbucketsize / (pcbucketsize / nsub)
for lb := b - len(funcbucket); lb >= 0; lb-- {
funcbucket = append(funcbucket, findfuncbucket{
idx: uint32(k)})
for k := 0; k < len(linker._funcs); k++ {
lEntry := int(getfuncentry(linker._funcs[k], module.text) - module.text)
lb := lEntry / pcbucketsize
li := lEntry % pcbucketsize / (pcbucketsize / nsub)

entry := int(module.maxpc - module.text)
if k < len(linker._funcs)-1 {
entry = int(getfuncentry(linker._funcs[k+1], module.text) - module.text)
}
b := entry / pcbucketsize
i := entry % pcbucketsize / (pcbucketsize / nsub)

for m := b - len(funcbucket); m >= 0; m-- {
funcbucket = append(funcbucket, findfuncbucket{idx: uint32(k)})
}
if lb < b {
i = nsub - 1
}
if funcbucket[b].subbuckets[i] == 0 && b != 0 && i != 0 {
if k-int(funcbucket[b].idx) >= pcbucketsize/minfunc {
return fmt.Errorf("over %d func in one funcbuckets", k-int(funcbucket[b].idx))
for n := li + 1; n <= i; n++ {
if funcbucket[lb].subbuckets[n] == 0 {
funcbucket[lb].subbuckets[n] = byte(k - int(funcbucket[lb].idx))
}
funcbucket[b].subbuckets[i] = byte(k - int(funcbucket[b].idx))
}
}
length := len(funcbucket) * FindFuncBucketSize
Expand Down

2 comments on commit 2fbc174

@fumeboy
Copy link

@fumeboy fumeboy commented on 2fbc174 Dec 3, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

这是我的写法:

			target := len(tab.FTab)             // 被计算索引的目的地址, 对应你程序里的 k
			bucket_idx := off / 4096            // 大桶
			subbucket_idx := (off % 4096) / 256 // 小桶

			// 如果没有对应的大桶, 则新建大桶, 需要注意大桶的起始索引应该是上一个大桶的最后一个索引项, 因为前一个函数的地址可能刚好跨越了4KB
			// 总是这样假设, 最多导致 findfunc 多循环一次, 没有什么开销
			if bucket_idx >= uintptr(len(tab.FindFuncBucket)) {
				var last_idx uint32
				if target == 0 {
					last_idx = 0
				} else {
					last_idx = uint32(target - 1)
				}
				for lb := int(bucket_idx) - len(tab.FindFuncBucket); lb >= 0; lb-- {
					tab.FindFuncBucket = append(tab.FindFuncBucket, findfuncbucket{Idx: last_idx})
				}
			}

			// 绕开地址所在小桶, 因为小桶可能是前一个函数地址的延续, 绕开实际上就是总是假设会出现这种情况, 而且绕开也最多导致 findfunc 多循环一次, 没有什么开销
			for subbucket_idx := subbucket_idx + 1; /*不设置地址所在小桶*/ subbucket_idx < 16; subbucket_idx++ { // 而是设置剩余小桶
				tab.FindFuncBucket[bucket_idx].Subbuckets[subbucket_idx] = byte(target - int(tab.FindFuncBucket[bucket_idx].Idx)) // 减去大桶的 idx 字段
			}

@pkujhd
Copy link
Owner Author

@pkujhd pkujhd commented on 2fbc174 Dec 4, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

这是我的写法:

			target := len(tab.FTab)             // 被计算索引的目的地址, 对应你程序里的 k
			bucket_idx := off / 4096            // 大桶
			subbucket_idx := (off % 4096) / 256 // 小桶

			// 如果没有对应的大桶, 则新建大桶, 需要注意大桶的起始索引应该是上一个大桶的最后一个索引项, 因为前一个函数的地址可能刚好跨越了4KB
			// 总是这样假设, 最多导致 findfunc 多循环一次, 没有什么开销
			if bucket_idx >= uintptr(len(tab.FindFuncBucket)) {
				var last_idx uint32
				if target == 0 {
					last_idx = 0
				} else {
					last_idx = uint32(target - 1)
				}
				for lb := int(bucket_idx) - len(tab.FindFuncBucket); lb >= 0; lb-- {
					tab.FindFuncBucket = append(tab.FindFuncBucket, findfuncbucket{Idx: last_idx})
				}
			}

			// 绕开地址所在小桶, 因为小桶可能是前一个函数地址的延续, 绕开实际上就是总是假设会出现这种情况, 而且绕开也最多导致 findfunc 多循环一次, 没有什么开销
			for subbucket_idx := subbucket_idx + 1; /*不设置地址所在小桶*/ subbucket_idx < 16; subbucket_idx++ { // 而是设置剩余小桶
				tab.FindFuncBucket[bucket_idx].Subbuckets[subbucket_idx] = byte(target - int(tab.FindFuncBucket[bucket_idx].Idx)) // 减去大桶的 idx 字段
			}

结果是一样的,只是最后一个桶,对于没有指令的字节,我没有填充,你填充成了len(func) -1

Please sign in to comment.