Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

helpers: Added dynamic symbol resolver #128

Merged
merged 5 commits into from Feb 16, 2022
Merged
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
50 changes: 36 additions & 14 deletions helpers/elf.go
Expand Up @@ -6,19 +6,9 @@ import (
"fmt"
)

// SymbolToOffset attempts to resolve a 'symbol' name in the binary found at
// 'path' to an offset. The offset can be used for attaching a u(ret)probe
func SymbolToOffset(path, symbol string) (uint32, error) {
f, err := elf.Open(path)
if err != nil {
return 0, fmt.Errorf("could not open elf file to resolve symbol offset: %w", err)
}

syms, err := f.Symbols()
if err != nil {
return 0, fmt.Errorf("could not open symbol section to resolve symbol offset: %w", err)
}

// symbolToOffset attempts to resolve a 'symbol' name in the given binary to an offset.
// The offset can be used for attaching a u(ret)probe.
func symbolToOffset(symbol string, f *elf.File, syms []elf.Symbol) (uint32, error) {
sectionsToSearchForSymbol := []*elf.Section{}

for i := range f.Sections {
Expand Down Expand Up @@ -48,5 +38,37 @@ func SymbolToOffset(path, symbol string) (uint32, error) {
}
}

return 0, fmt.Errorf("symbol not found")
return 0, errors.New("symbol not found")
guyarb marked this conversation as resolved.
Show resolved Hide resolved
}

// SymbolToOffset attempts to resolve a 'symbol' name in the binary found at
// 'path' to an offset. The offset can be used for attaching a u(ret)probe
func SymbolToOffset(path, symbol string) (uint32, error) {
f, err := elf.Open(path)
if err != nil {
return 0, fmt.Errorf("could not open elf file to resolve symbol offset: %w", err)
}

syms, err := f.Symbols()
if err != nil {
return 0, fmt.Errorf("could not open symbol section to resolve symbol offset: %w", err)
}

return symbolToOffset(symbol, f, syms)
}

// DynamicSymbolToOffset attempts to resolve a dynamic 'symbol' name in the binary found at
// 'path' to an offset. The offset can be used for attaching a u(ret)probe
func DynamicSymbolToOffset(path, symbol string) (uint32, error) {
Copy link
Contributor

Choose a reason for hiding this comment

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

What do you think about adding this logic to SymbolToOffset instead? If the named symbol isn't in the symbol table, check dynamic symbols. Is it possible to have a name collision?

Copy link
Contributor Author

@guyarb guyarb Feb 15, 2022

Choose a reason for hiding this comment

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

I'm in favor of your suggestion, I didn't want to "break" anyone using the original function, so ill change the code accordingly.

regarding the name collision - so the short answer would be yes, but it is only because the dynamic symbol table contains exported functions that will appear in the regular symbol table.

a nice answer in stack overflow https://reverseengineering.stackexchange.com/a/21623

Copy link
Contributor Author

Choose a reason for hiding this comment

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

created a simple SO (followed https://www.cprogramming.com/tutorial/shared-libraries-linux-gcc.html)
and checked both the regular symbol table and the dynamic symbol table
you can see the duplications
image

f, err := elf.Open(path)
if err != nil {
return 0, fmt.Errorf("could not open elf file to resolve symbol offset: %w", err)
}

syms, err := f.DynamicSymbols()
if err != nil {
return 0, fmt.Errorf("could not open dynamic symbol section to resolve symbol offset: %w", err)
}

return symbolToOffset(symbol, f, syms)
}