рдЧреЛ рдореЗрдВ рдИрдПрд▓рдПрдл рдЯреНрд░рд┐рдХ


рдЗрд╕ рдиреЛрдЯ рдореЗрдВ, рд╣рдо рд╕реАрдЦреЗрдВрдЧреЗ рдХрд┐ рдПрдХ рд░рди рдлрд╝рдВрдХреНрд╢рди рдХреЗ рдорд╢реАрди рдХреЛрдб рдХреЛ рд╕реАрдзреЗ рд░рдирдЯрд╛рдЗрдо рдореЗрдВ рдХреИрд╕реЗ рдкреНрд░рд╛рдкреНрдд рдХрд░реЗрдВ, рдПрдХ рдбрд┐рд╕реНрд╕реЗрдореНрдмрд▓рд░ рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рдХреЗ рдЗрд╕реЗ рдкреНрд░рд┐рдВрдЯ рдХрд░реЗрдВ, рдФрд░ рдЬрд┐рд╕ рддрд░рд╣ рд╕реЗ рд╣рдо рдмрд┐рдирд╛ рдХреЙрд▓ рдХрд┐рдП рдлрд╝рдВрдХреНрд╢рди рдХреЗ рдкрддреЗ рдХреЛ рдкреНрд░рд╛рдкреНрдд рдХрд░рдиреЗ рдЬреИрд╕реЗ рдХрдИ рддрд░рдХреАрдмреЛрдВ рдХрд╛ рдкрддрд╛ рд▓рдЧрд╛рдПрдВрдЧреЗред


рдЪреЗрддрд╛рд╡рдиреА : рдпрд╣ рд▓рдШреБ-рд▓реЗрдЦ рдЖрдкрдХреЛ рдЙрдкрдпреЛрдЧреА рдХреБрдЫ рднреА рдирд╣реАрдВ рд╕рд┐рдЦрд╛рдПрдЧрд╛ред


рдЬрд╛рдУ рдореЗрдВ рд╕рдорд╛рд░реЛрд╣ рдореВрд▓реНрдп


рд╕рдмрд╕реЗ рдкрд╣рд▓реЗ, рдпрд╣ рдирд┐рд░реНрдзрд╛рд░рд┐рдд рдХрд░реЗрдВ рдХрд┐ рдПрдХ рдЧреЛ рдлрд╝рдВрдХреНрд╢рди рдХреНрдпрд╛ рд╣реИ рдФрд░ рд╣рдореЗрдВ рдлрд╝рдВрдХреНрд╢рди рдорд╛рди рдХреА рдЕрд╡рдзрд╛рд░рдгрд╛ рдХреА рдЖрд╡рд╢реНрдпрдХрддрд╛ рдХреНрдпреЛрдВ рд╣реИред


рдпрд╣ рдЧреЛ 1.1 рдлрд╝рдВрдХреНрд╢рди рдХреЙрд▓ рджрд╕реНрддрд╛рд╡реЗрдЬрд╝ рджреНрд╡рд╛рд░рд╛ рд╕рдмрд╕реЗ рдЕрдЪреНрдЫреА рддрд░рд╣ рд╕реЗ рд╕рдордЭрд╛рдпрд╛ рдЧрдпрд╛ рд╣реИред рджрд╕реНрддрд╛рд╡реЗрдЬрд╝ рдирдпрд╛ рдирд╣реАрдВ рд╣реИ, рд▓реЗрдХрд┐рди рдЗрд╕рдореЗрдВ рдЕрдзрд┐рдХрд╛рдВрд╢ рдЬрд╛рдирдХрд╛рд░реА рдЕрднреА рднреА рдкреНрд░рд╛рд╕рдВрдЧрд┐рдХ рд╣реИред


рдирд┐рдореНрдирддрдо рд╕реНрддрд░ рдкрд░, рдпрд╣ рд╣рдореЗрд╢рд╛ рдирд┐рд╖реНрдкрд╛рджрди рдпреЛрдЧреНрдп рдХреЛрдб рдХреЗ рд▓рд┐рдП рдПрдХ рд╕рдВрдХреЗрддрдХ рд╣реИ, рд▓реЗрдХрд┐рди рдЬрдм рд╣рдо рдЕрдирд╛рдо рдлрд╝рдВрдХреНрд╢рди / рдХреНрд▓реЛрдЬрд░ рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рддреЗ рд╣реИрдВ рдпрд╛ interface{} рд░реВрдк рдореЗрдВ рдПрдХ рдлрд╝рдВрдХреНрд╢рди рдкрд╛рд╕ рдХрд░рддреЗ рд╣реИрдВ, рддреЛ рдпрд╣ рд╕реВрдЪрдХ рдХреБрдЫ рд╕рдВрд░рдЪрдирд╛ рдХреЗ рдЕрдВрджрд░ рдЫрд┐рдкрд╛ рд╣реЛрддрд╛ рд╣реИред


рдлрд╝рдВрдХреНрд╢рди рдирд╛рдо рдЕрдкрдиреЗ рдЖрдк рдореЗрдВ рдПрдХ рдЕрднрд┐рд╡реНрдпрдХреНрддрд┐ рдирд╣реАрдВ рд╣реИ, рдЗрд╕рд▓рд┐рдП, рдРрд╕рд╛ рдХреЛрдб рдХрд╛рдо рдирд╣реАрдВ рдХрд░рддрд╛ рд╣реИ:


 // https://play.golang.org/p/wXeVLU7nLPs package main func add1(x int) int { return 1 } func main() { addr := &add1 println(addr) } 

compile: cannot take the address of add1

рд▓реЗрдХрд┐рди рдПрдХ рд╣реА рд╕рдордп рдореЗрдВ, рд╣рдо рдПрдХ рд╣реА рдлрд╝рдВрдХреНрд╢рди рдирд╛рдо рдХреЗ рдорд╛рдзреНрдпрдо рд╕реЗ function value рдкреНрд░рд╛рдкреНрдд рдХрд░ рд╕рдХрддреЗ рд╣реИрдВ:


 // https://play.golang.org/p/oWqv_FQq4hy package main func add1(x int) int { return 1 } func main() { f := add1 // <-------- addr := &f println(addr) } 

рдпрд╣ рдХреЛрдб рд▓реЙрдиреНрдЪ рдХрд┐рдпрд╛ рдЧрдпрд╛ рд╣реИ, рд▓реЗрдХрд┐рди рдпрд╣ рд╕реНрдЯреИрдХ рдкрд░ рдПрдХ рд╕реНрдерд╛рдиреАрдп рд╡реИрд░рд┐рдПрдмрд▓ рдХреЗ рдкрддреЗ рдХреЛ рдкреНрд░рд┐рдВрдЯ рдХрд░реЗрдЧрд╛, рдЬреЛ рдХрд┐ рд╡рд╛рд╕реНрддрд╡ рдореЗрдВ рд╣рдо рдирд╣реАрдВ рдЪрд╛рд╣рддреЗ рдереЗред рд▓реЗрдХрд┐рди, рдЬреИрд╕рд╛ рдХрд┐ рдКрдкрд░ рдЙрд▓реНрд▓реЗрдЦ рдХрд┐рдпрд╛ рдЧрдпрд╛ рд╣реИ, рдлрд╝рдВрдХреНрд╢рди рдХрд╛ рдкрддрд╛ рдЕрднреА рднреА рд╣реИ, рдЖрдкрдХреЛ рдмрд╕ рдпрд╣ рдЬрд╛рдирдиреЗ рдХреА рдЖрд╡рд╢реНрдпрдХрддрд╛ рд╣реИ рдХрд┐ рдЗрд╕реЗ рдХреИрд╕реЗ рдПрдХреНрд╕реЗрд╕ рдХрд┐рдпрд╛ рдЬрд╛рдПред


reflect рдкреИрдХреЗрдЬ рд╕рдлрд▓рддрд╛рдкреВрд░реНрд╡рдХ рд▓рд╛рдЧреВ рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП рдЗрд╕ рдХрд╛рд░реНрдпрд╛рдиреНрд╡рдпрди рд╡рд┐рд╡рд░рдг рдкрд░ рдирд┐рд░реНрднрд░ рдХрд░рддрд╛ рд╣реИред reflect.Value.Call() ред рд╡рд╣рд╛рдБ (рдкреНрд░рддрд┐рдмрд┐рдВрдмрд┐рдд / makefunc.go) рдЖрдк рдлрд╝рдВрдХреНрд╢рди рдХрд╛ рдкрддрд╛ рдкреНрд░рд╛рдкреНрдд рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП рдЕрдЧрд▓реЗ рдЪрд░рдг рдХреА рдЬрд╛рд╕реВрд╕реА рдХрд░ рд╕рдХрддреЗ рд╣реИрдВ:


 dummy := makeFuncStub code := **(**uintptr)(unsafe.Pointer(&dummy)) 

рдЙрдкрд░реЛрдХреНрдд рдХреЛрдб рдПрдХ рдореВрд▓ рд╡рд┐рдЪрд╛рд░ рдкреНрд░рджрд░реНрд╢рд┐рдд рдХрд░рддрд╛ рд╣реИ рдЬрд┐рд╕реЗ рдЖрдк рдХрд┐рд╕реА рдлрд╝рдВрдХреНрд╢рди рдХреЛ рдкрд░рд┐рд╖реНрдХреГрдд рдХрд░ рд╕рдХрддреЗ рд╣реИрдВ:


 // funcAddr returns function value fn executable code address. func funcAddr(fn interface{}) uintptr { // emptyInterface is the header for an interface{} value. type emptyInterface struct { typ uintptr value *uintptr } e := (*emptyInterface)(unsafe.Pointer(&fn)) return *e.value } 

add1 рдлрд╝рдВрдХреНрд╢рди add1 рдХреЛ funcAddr(add1) рдХреЙрд▓ рдХрд░рдХреЗ add1 рдХрд┐рдпрд╛ рдЬрд╛ рд╕рдХрддрд╛ рд╣реИред


рдорд╢реАрди рдлрд╝рдВрдХреНрд╢рди рдХреЛрдб рдХрд╛ рдмреНрд▓реЙрдХ рдкреНрд░рд╛рдкреНрдд рдХрд░рдирд╛


рдЕрдм рдЬрдм рд╣рдорд╛рд░реЗ рдкрд╛рд╕ рдлрд╝рдВрдХреНрд╢рди рдХреЗ рдорд╢реАрди рдХреЛрдб рдХреА рд╢реБрд░реБрдЖрдд рдХрд╛ рдкрддрд╛ рд╣реИ, рддреЛ рд╣рдо рдлрд╝рдВрдХреНрд╢рди рдХреЗ рдкреВрд░реЗ рдорд╢реАрди рдХреЛрдб рдХреЛ рдкреНрд░рд╛рдкреНрдд рдХрд░рдирд╛ рдЪрд╛рд╣рддреЗ рд╣реИрдВред рдпрд╣рд╛рдВ рдЖрдкрдХреЛ рдпрд╣ рдирд┐рд░реНрдзрд╛рд░рд┐рдд рдХрд░рдиреЗ рдореЗрдВ рд╕рдХреНрд╖рдо рд╣реЛрдиреЗ рдХреА рдЖрд╡рд╢реНрдпрдХрддрд╛ рд╣реИ рдХрд┐ рд╡рд░реНрддрдорд╛рди рдлрд╝рдВрдХреНрд╢рди рдХрд╛ рдХреЛрдб рдХрд╣рд╛рдВ рд╕рдорд╛рдкреНрдд рд╣реЛрддрд╛ рд╣реИред


рдпрджрд┐ x86 рдЖрд░реНрдХрд┐рдЯреЗрдХреНрдЪрд░ рдиреЗ рдирд┐рд╢реНрдЪрд┐рдд-рд▓рдВрдмрд╛рдИ рдирд┐рд░реНрджреЗрд╢ рджрд┐рдП рдереЗ, рддреЛ рдпрд╣ рдЗрддрдирд╛ рдореБрд╢реНрдХрд┐рд▓ рдирд╣реАрдВ рд╣реЛрдЧрд╛ рдФрд░ рдХрдИ рдЙрддреНрддрд░рд╛рдзрд┐рдХрд╛рд░реА рд╣рдорд╛рд░реА рдорджрдж рдХрд░ рд╕рдХрддреЗ рд╣реИрдВ, рдЬрд┐рдирдореЗрдВ рд╕реЗ:


  • рдПрдХ рдирд┐рдпрдо рдХреЗ рд░реВрдк рдореЗрдВ, рдлрд╝рдВрдХреНрд╢рди рдХреЛрдб рдХреЗ рдЕрдВрдд рдореЗрдВ INT3 рдирд┐рд░реНрджреЗрд╢реЛрдВ рд╕реЗ рдПрдХ рдмреАрдЯ рд╣реИред рдпрд╣ рдлрд╝рдВрдХреНрд╢рди рдХреЛрдб рдХреЗ рдЕрдВрдд рдХреЗ рд▓рд┐рдП рдПрдХ рдЕрдЪреНрдЫрд╛ рдорд╛рд░реНрдХрд░ рд╣реИ, рд▓реЗрдХрд┐рди рдпрд╣ рдЧрд╛рдпрдм рд╣реЛ рд╕рдХрддрд╛ рд╣реИред
  • рд╕реНрдЯреИрдХ рдХреЗ рд▓рд┐рдП рдПрдХ рдЧреИрд░-рд╢реВрдиреНрдп рдлреНрд░реЗрдо рд╡рд╛рд▓реЗ рдХрд╛рд░реНрдпреЛрдВ рдореЗрдВ рдПрдХ рдкреНрд░реЛрд▓реЙрдЧ рд╣реЛрддрд╛ рд╣реИ рдЬреЛ рдпрд╣ рдЬрд╛рдВрдЪрддрд╛ рд╣реИ рдХрд┐ рдХреНрдпрд╛ рдЗрд╕ рд╕реНрдЯреИрдХ рдХреЛ рд╡рд┐рд╕реНрддрд╛рд░рд┐рдд рдХрд░рдиреЗ рдХреА рдЖрд╡рд╢реНрдпрдХрддрд╛ рд╣реИред рдпрджрд┐ рд╣рд╛рдБ, рддреЛ рдлрд╝рдВрдХреНрд╢рди рдХреЛрдб рдХреЗ рддреБрд░рдВрдд рдмрд╛рдж рдХреЛрдб рдХреЗ рд▓рд┐рдП рдПрдХ рдХреВрдж рдХрд┐рдпрд╛ рдЬрд╛рддрд╛ рд╣реИ, рдФрд░ рдлрд┐рд░ рдлрд╝рдВрдХреНрд╢рди рдХреА рд╢реБрд░реБрдЖрдд рдХреЗ рд▓рд┐рдП рдПрдХ рдХреВрджред рдЬрд┐рд╕ рдХреЛрдб рдореЗрдВ рд╣рдо рд░реБрдЪрд┐ рд░рдЦрддреЗ рд╣реИрдВ, рд╡рд╣ рдордзреНрдп рдореЗрдВ рд╣реЛрдЧрд╛ред

рд▓реЗрдХрд┐рди рдЖрдкрдХреЛ рдирд┐рд░реНрджреЗрд╢реЛрдВ рдХреЛ рдИрдорд╛рдирджрд╛рд░реА рд╕реЗ рдбрд┐рдХреЛрдб рдХрд░рдиреЗ рдХреА рдЖрд╡рд╢реНрдпрдХрддрд╛ рд╣реЛрдЧреА, рдХреНрдпреЛрдВрдХрд┐ рдПрдХ рдмрд╛рдЗрдЯ-рджрд░-рдкрд╛рд╕ рджреВрд╕рд░реЗ рдирд┐рд░реНрджреЗрд╢ рдХреЗ рдЕрдВрджрд░ INT3 рдмрд╛рдЗрдЯ рдкрд╛ рд╕рдХрддреЗ рд╣реИрдВред рд╕реНрдХрд┐рдк рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП рдПрдХ рдирд┐рд░реНрджреЗрд╢ рдХреА рд▓рдВрдмрд╛рдИ рдХреА рдЧрдгрдирд╛ рдХрд░рдирд╛ рднреА рдЗрддрдирд╛ рдЖрд╕рд╛рди рдирд╣реАрдВ рд╣реИ, рдХреНрдпреЛрдВрдХрд┐ рдпрд╣ x86, рдмреЗрдмреА рд╣реИ ред


runtime рдкреИрдХреЗрдЬ рдХреЗ рд╕рдВрджрд░реНрдн рдореЗрдВ рдПрдХ рдлрд╝рдВрдХреНрд╢рди рдХрд╛ рдкрддрд╛ рдХрднреА-рдХрднреА рдлрд╝рдВрдХреНрд╢рди рдХреЗ рдЕрдВрджрд░ рдХрд╣реАрдВ рдФрд░ рдкрддреЗ рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рдиреЗ рдХреА рдХреНрд╖рдорддрд╛ рдкрд░ рдЬреЛрд░ рджреЗрдиреЗ рдХреЗ рд▓рд┐рдП, PC рдХреЛ рдХрд╣рд╛ рдЬрд╛рддрд╛ рд╣реИ, рдФрд░ рди рдХреЗрд╡рд▓ рдлрд╝рдВрдХреНрд╢рди рдХрд╛ рдкреНрд░рд╡реЗрд╢ рдмрд┐рдВрджреБред funcAddr рдкрд░рд┐рдгрд╛рдо рдХрд╛ рдЙрдкрдпреЛрдЧ funcAddr рддрд░реНрдХ рдХреЗ рд░реВрдк рдореЗрдВ рдХрд┐рдпрд╛ рдЬрд╛ рд╕рдХрддрд╛ рд╣реИред funcAddr runtime.FuncForPC() рдлрд╝рдВрдХреНрд╢рди рдХреЛ funcAddr рдкреНрд░рд╛рдкреНрдд рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдПред рдлрд╝рдВрдХреНрд╢рди рдХреЛ рдХреЙрд▓ рдХрд┐рдП рдмрд┐рдирд╛ред рдЕрд╕реБрд░рдХреНрд╖рд┐рдд рдирдП рд╕рд╛рд▓ рдХреЗ рдкрд░рд┐рд╡рд░реНрддрдиреЛрдВ рдХреЗ рдорд╛рдзреНрдпрдо рд╕реЗ, рд╣рдо runtime._func рддрдХ рдкрд╣реБрдБрдЪ рд╕рдХрддреЗ рд╣реИрдВред runtime._func , рдЬреЛ рдЬрд╛рдирдХрд╛рд░реАрдкреВрд░реНрдг рд╣реИ, рд▓реЗрдХрд┐рди рдмрд╣реБрдд рдЙрдкрдпреЛрдЧреА рдирд╣реАрдВ рд╣реИ: рдлрд╝рдВрдХреНрд╢рди рдХреЛрдб рдмреНрд▓реЙрдХ рдХреЗ рдЖрдХрд╛рд░ рдХреЗ рдмрд╛рд░реЗ рдореЗрдВ рдХреЛрдИ рдЬрд╛рдирдХрд╛рд░реА рдирд╣реАрдВ рд╣реИред


рдРрд╕рд╛ рд▓рдЧрддрд╛ рд╣реИ рдХрд┐ рдИрдПрд▓рдПрдл рдХреА рдорджрдж рдХреЗ рдмрд┐рдирд╛ рд╣рдо рд╕рд╛рдордирд╛ рдирд╣реАрдВ рдХрд░ рд╕рдХрддреЗред


рдЙрди рдкреНрд▓реЗрдЯрдлрд╝реЙрд░реНрдо рдХреЗ рд▓рд┐рдП рдЬрд╣рд╛рдВ рдПрдХреНрдЬрд╝реАрдХреНрдпреВрдЯреЗрдмрд▓реНрд╕ рдХрд╛ рдПрдХ рдЕрд▓рдЧ рдкреНрд░рд╛рд░реВрдк рд╣реИ, рдЕрдзрд┐рдХрд╛рдВрд╢ рд▓реЗрдЦ рдкреНрд░рд╛рд╕рдВрдЧрд┐рдХ рд░рд╣реЗрдВрдЧреЗ, рд▓реЗрдХрд┐рди рдЖрдкрдХреЛ debug/elf рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рдиреЗ рдХреА рдЖрд╡рд╢реНрдпрдХрддрд╛ рдирд╣реАрдВ рд╣реЛрдЧреА, рд▓реЗрдХрд┐рди debug рд╕реЗ рдПрдХ рдФрд░ рдкреИрдХреЗрдЬред

рдИрдПрд▓рдПрдл рдЬреЛ рдЖрдкрдХреЗ рдХрд╛рд░реНрдпрдХреНрд░рдо рдореЗрдВ рдЫрд┐рдкрд╛ рд╣реИ


рд╣рдореЗрдВ рдЬреЛ рдЬрд╛рдирдХрд╛рд░реА рдЪрд╛рд╣рд┐рдП рд╡рд╣ рдкрд╣рд▓реЗ рд╕реЗ рд╣реА рдИрдПрд▓рдПрдл рдлрд╝рд╛рдЗрд▓ рдХреЗ рдореЗрдЯрд╛рдбреЗрдЯрд╛ рдореЗрдВ рдирд┐рд╣рд┐рдд рд╣реИред


os.Args[0] рдорд╛рдзреНрдпрдо рд╕реЗ os.Args[0] рд╣рдо рдирд┐рд╖реНрдкрд╛рджрди рдпреЛрдЧреНрдп рдлрд╝рд╛рдЗрд▓ рдХреЛ рд╕реНрд╡рдпрдВ рдПрдХреНрд╕реЗрд╕ рдХрд░ рд╕рдХрддреЗ рд╣реИрдВ, рдФрд░ рдкрд╣рд▓реЗ рд╕реЗ рд╣реА рдкреНрд░рддреАрдХ рддрд╛рд▓рд┐рдХрд╛ рдкреНрд░рд╛рдкреНрдд рдХрд░ рд╕рдХрддреЗ рд╣реИрдВред


 func readELF() (*elf.File, error) { f, err := os.Open(os.Args[0]) if err != nil { return nil, fmt.Errorf("open argv[0]: %w", err) } return elf.NewFile(f) } 

elf.File рдЕрдВрджрд░ рдПрдХ рдЪрд░рд┐рддреНрд░ рдХреЗ рд▓рд┐рдП рдЦреЛрдЬреЗрдВ


рд╕рднреА рд╡рд░реНрдгреЛрдВ рдХреЛ File.Symbols() рд╡рд┐рдзрд┐ рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рдХреЗ File.Symbols() рдХрд┐рдпрд╛ рдЬрд╛ рд╕рдХрддрд╛ рд╣реИред рдпрд╣ рд╡рд┐рдзрд┐ рд▓реМрдЯрд╛рддреА рд╣реИ []elf.Symbol , рдЬрд┐рд╕рдореЗрдВ Symbol.Size рдлрд╝реАрд▓реНрдб рд╢рд╛рдорд┐рд▓ рд╣реИ - рдпрд╣ "рдлрд╝рдВрдХреНрд╢рди рдЖрдХрд╛рд░" рд╣реИ рдЬрд┐рд╕реЗ рд╣рдо Symbol.Size ред Symbol.Value рдлрд╝реАрд▓реНрдб рдХреЛ funcAddr рджреНрд╡рд╛рд░рд╛ funcAddr рдЧрдП рдорд╛рди рд╕реЗ рдореЗрд▓ рдЦрд╛рдирд╛ рдЪрд╛рд╣рд┐рдПред


рдЖрдк рд╡рд╛рдВрдЫрд┐рдд рдкреНрд░рддреАрдХ (рдкрддреЗ) ( Symbol.Value ) рдпрд╛ рдирд╛рдо ( Symbol.Name ) рджреНрд╡рд╛рд░рд╛ рдЦреЛрдЬ рд╕рдХрддреЗ рд╣реИрдВред рдпрджрд┐ рд╡рд░реНрдг рдирд╛рдо рд╕реЗ рдХреНрд░рдордмрджреНрдз рд╣реЛрддреЗ рд╣реИрдВ, рддреЛ sort.Search() рд╕рдВрднрд╡ рд╣реЛрдЧрд╛ред sort.Search() , рд▓реЗрдХрд┐рди рдпрд╣ рдРрд╕рд╛ рдирд╣реАрдВ рд╣реИ:


рдкреНрд░рддреАрдХреЛрдВ рдХреЛ рдЙрд╕ рдХреНрд░рдо рдореЗрдВ рд╕реВрдЪреАрдмрджреНрдз рдХрд┐рдпрд╛ рдЬрд╛рдПрдЧрд╛ рдЬреЛ рд╡реЗ рдлрд╝рд╛рдЗрд▓ рдореЗрдВ рджрд┐рдЦрд╛рдИ рджреЗрддреЗ рд╣реИрдВред

рдпрджрд┐ рдЖрдкрдХреЛ рдЕрдХреНрд╕рд░ рддрд╛рд▓рд┐рдХрд╛ рдореЗрдВ рд╡рд░реНрдг рдЦреЛрдЬрдиреЗ рдХреА рдЖрд╡рд╢реНрдпрдХрддрд╛ рд╣реЛрддреА рд╣реИ, рддреЛ рдЖрдкрдХреЛ рдПрдХ рдЕрддрд┐рд░рд┐рдХреНрдд рд╕реВрдЪрдХрд╛рдВрдХ рдмрдирд╛рдирд╛ рдЪрд╛рд╣рд┐рдП, рдЙрджрд╛рд╣рд░рдг рдХреЗ рд▓рд┐рдП, map[string]*elf.Symbol рдпрд╛ map[uintptr]*elf.Symbol ред


рдЪреВрдВрдХрд┐ рд╣рдо рдкрд╣рд▓реЗ рд╕реЗ рд╣реА рдЬрд╛рдирддреЗ рд╣реИрдВ рдХрд┐ рдХрд┐рд╕реА рдлрд╝рдВрдХреНрд╢рди рдХрд╛ рдкрддрд╛ рдЙрд╕рдХреЗ рдореВрд▓реНрдп рд╕реЗ рдХреИрд╕реЗ рдкреНрд░рд╛рдкреНрдд рдХрд┐рдпрд╛ рдЬрд╛рдП, рддреЛ рд╣рдо рдЙрд╕рдХреА рдЦреЛрдЬ рдХрд░реЗрдВрдЧреЗ:


 func elfLookup(f *elf.File, value uint64) *elf.Symbol { symbols, err := f.Symbols() if err != nil { return nil } for _, sym := range symbols { if sym.Value == value { return &sym } } return nil } 

рдиреЛрдЯ : рдХрд╛рдо рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП рдЗрд╕ рджреГрд╖реНрдЯрд┐рдХреЛрдг рдХреЗ рд▓рд┐рдП, рд╣рдореЗрдВ рдПрдХ рдЪрд░рд┐рддреНрд░ рддрд╛рд▓рд┐рдХрд╛ рдЪрд╛рд╣рд┐рдПред рдпрджрд┐ рдмрд╛рдЗрдирд░реА рдХреЛ ` -ldflags "-s" 'рдХреЗ рд╕рд╛рде рдмрдирд╛рдпрд╛ рдЧрдпрд╛ рд╣реИ, рддреЛ elfLookup() рд╣рдореЗрд╢рд╛ nil рд▓реМрдЯреЗрдЧрд╛ред рдпрджрд┐ рдЖрдк go run рдорд╛рдзреНрдпрдо рд╕реЗ рдкреНрд░реЛрдЧреНрд░рд╛рдо go run рддреЛ рдЖрдк рдЙрд╕реА рд╕рдорд╕реНрдпрд╛ рдХрд╛ рд╕рд╛рдордирд╛ рдХрд░ рд╕рдХрддреЗ рд╣реИрдВред рд▓реЗрдЦ рд╕реЗ рдЙрджрд╛рд╣рд░рдг рдХреЗ рд▓рд┐рдП, рдирд┐рд╖реНрдкрд╛рджрди рдпреЛрдЧреНрдп рдлрд╝рд╛рдЗрд▓реЛрдВ рдХреЛ рдкреНрд░рд╛рдкреНрдд рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП ' go build ' рдпрд╛ ' go install ' рдХрд░рдиреЗ рдХреА рд╕рд┐рдлрд╛рд░рд┐рд╢ рдХреА рдЬрд╛рддреА рд╣реИред

рдорд╢реАрди рдлрд╝рдВрдХреНрд╢рди рдХреЛрдб рдкреНрд░рд╛рдкреНрдд рдХрд░рдирд╛


рдирд┐рд╖реНрдкрд╛рджрди рдпреЛрдЧреНрдп рдХреЛрдб рдХреЗ рдкрддреЗ рдХреА рд╕реАрдорд╛ рдЬрд╛рдирдиреЗ рдХреЗ рдмрд╛рдж, рдпрд╣ рдХреЗрд╡рд▓ рд╕реБрд╡рд┐рдзрд╛рдЬрдирдХ рдкреНрд░рд╕рдВрд╕реНрдХрд░рдг рдХреЗ рд▓рд┐рдП []byte рдХреЗ рд░реВрдк рдореЗрдВ рдЗрд╕реЗ рдмрд╛рд╣рд░ рдирд┐рдХрд╛рд▓рдирд╛ рд╣реИред


 func funcCode(addr uintptr) ([]byte, error) { elffile, err := readELF() if err != nil { return nil, fmt.Errorf("read elf: %w", err) } sym := elfLookup(elffile, uint64(addr)) if sym == nil { return nil, fmt.Errorf("can't lookup symbol for %x", addr) } code := *(*[]byte)(unsafe.Pointer(&reflect.SliceHeader{ Data: addr, Len: int(sym.Size), Cap: int(sym.Size), })) return code, nil } 

рдпрд╣ рдХреЛрдб рдЬрд╛рдирдмреВрдЭрдХрд░ рдкреНрд░рджрд░реНрд╢рди рдХреЗ рд▓рд┐рдП рд╕рд░рд▓ рдмрдирд╛рдпрд╛ рдЧрдпрд╛ рд╣реИред рдЖрдкрдХреЛ рд╣рд░ рдмрд╛рд░ ELF рдирд╣реАрдВ рдкрдврд╝рдирд╛ рдЪрд╛рд╣рд┐рдП рдФрд░ рдЗрд╕рдХреА рдореЗрдЬ рдкрд░ рдПрдХ рд░реЗрдЦреАрдп рдЦреЛрдЬ рдХрд░рдиреА рдЪрд╛рд╣рд┐рдПред


funcCode() рдлрд╝рдВрдХреНрд╢рди рдХрд╛ рдкрд░рд┐рдгрд╛рдо рдорд╢реАрди рдлрд╝рдВрдХреНрд╢рди рдХреЛрдб рдХреЗ рдмрд╛рдЗрдЯреНрд╕ рдХреЗ рд╕рд╛рде рдПрдХ рдЯреБрдХрдбрд╝рд╛ рд╣реИред рдЙрд╕реЗ funcAddr() рдХреЙрд▓ funcAddr() рдкрд░рд┐рдгрд╛рдо funcAddr() рдХрд░рдирд╛ рдЪрд╛рд╣рд┐рдПред


 code, err := funcCode(funcAddr(add1)) if err != nil { log.Panicf("can't get function code: %v", err) } fmt.Printf("% x\n", code) // => 48 8b 44 24 08 48 ff c0 48 89 44 24 10 c3 

рдорд╢реАрди рдХреЛрдб рдЬреБрджрд╛ рдХрд░рдирд╛


рдорд╢реАрди рдХреЛрдб рдХреЛ рдкрдврд╝рдиреЗ рдХреЗ рд▓рд┐рдП рдЖрд╕рд╛рди рдмрдирд╛рдиреЗ рдХреЗ рд▓рд┐рдП, рд╣рдо рдПрдХ рдбрд┐рд╕реНрд╕реЗрдореНрдмрд▓рд░ рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░реЗрдВрдЧреЗред


рдореИрдВ рдкреНрд░реЛрдЬреЗрдХреНрдЯреНрд╕ zydis рдФрд░ Intel XED рд╕реЗ рд╕рдмрд╕реЗ рдЬреНрдпрд╛рджрд╛ рдкрд░рд┐рдЪрд┐рдд рд╣реВрдВ , рдЗрд╕рд▓рд┐рдП рд╕рдмрд╕реЗ рдкрд╣рд▓реЗ рдореЗрд░реА рдкрд╕рдВрдж рдЙрди рдкрд░ рдкрдбрд╝рддреА рд╣реИред


Go рдХреЗ рд▓рд┐рдП, рдЖрдк go-zydis рдмрд╛рдЗрдВрдбрд┐рдВрдЧ рд▓реЗ рд╕рдХрддреЗ рд╣реИрдВ, рдЬреЛ рдХрд┐ рд╣рдорд╛рд░реЗ рдХрд╛рд░реНрдп рдХреЗ рд▓рд┐рдП рдкрд░реНрдпрд╛рдкреНрдд рдФрд░ рдЖрд╕рд╛рди рд╣реИред


рдЖрдЗрдП рд╣рдо "рдорд╢реАрди рдирд┐рд░реНрджреЗрд╢реЛрдВ рдХреЛ рджрд░рдХрд┐рдирд╛рд░" рдХреЗ рдЕрдореВрд░реНрдд рд╡рд░реНрдгрди рдХрд░рддреЗ рд╣реИрдВ, рдЬрд┐рд╕рдХреА рдорджрдж рд╕реЗ рдЕрдиреНрдп рдХрд╛рд░реНрдпреЛрдВ рдХреЛ рд▓рд╛рдЧреВ рдХрд░рдирд╛ рд╕рдВрднрд╡ рд╣реИ:


 func walkDisasm(code []byte, visit func(*zydis.DecodedInstruction) error) error { dec := zydis.NewDecoder(zydis.MachineMode64, zydis.AddressWidth64) buf := code for len(buf) > 0 { instr, err := dec.Decode(buf) if err != nil { return err } if err := visit(instr); err != nil { return err } buf = buf[int(instr.Length):] } return nil } 

рдпрд╣ рдлрд╝рдВрдХреНрд╢рди рдЗрдирдкреБрдЯ рдХреЗ рд░реВрдк рдореЗрдВ рдПрдХ рдорд╢реАрди рдХреЛрдб рд╕реНрд▓рд╛рдЗрд╕ рд▓реЗрддрд╛ рд╣реИ рдФрд░ рдкреНрд░рддреНрдпреЗрдХ рдбрд┐рдХреЛрдб рдХрд┐рдП рдЧрдП рдирд┐рд░реНрджреЗрд╢ рдХреЗ рд▓рд┐рдП рдХреЙрд▓рдмреИрдХ рдлрд╝рдВрдХреНрд╢рди рдХреЛ рдХреЙрд▓ рдХрд░рддрд╛ рд╣реИред


рдЗрд╕рдХреЗ рдЖрдзрд╛рд░ рдкрд░, рд╣рдо printDisasm рд▓рд┐рдЦ рд╕рдХрддреЗ рд╣реИрдВ printDisasm рд╣рдореЗрдВ printDisasm :


 func printDisasm(code []byte) error { const ZYDIS_RUNTIME_ADDRESS_NONE = math.MaxUint64 formatter, err := zydis.NewFormatter(zydis.FormatterStyleIntel) if err != nil { return err } return walkDisasm(code, func(instr *zydis.DecodedInstruction) error { s, err := formatter.FormatInstruction(instr, ZYDIS_RUNTIME_ADDRESS_NONE) if err != nil { return err } fmt.Println(s) return nil }) } 

рдпрджрд┐ рд╣рдо add1 рдлрд╝рдВрдХреНрд╢рди add1 рдкрд░ printDisasm рдЪрд▓рд╛рддреЗ рд╣реИрдВ, рддреЛ рд╣рдореЗрдВ рд▓рдВрдмреЗ рд╕рдордп рд╕реЗ рдкреНрд░рддреАрдХреНрд╖рд┐рдд рдкрд░рд┐рдгрд╛рдо рдорд┐рд▓рддрд╛ рд╣реИ:


 mov rax, [rsp+0x08] inc rax mov [rsp+0x10], rax ret 

рдкрд░рд┐рдгрд╛рдо рдорд╛рдиреНрдпрддрд╛


рдЕрдм рд╣рдо рдпрд╣ рд╕реБрдирд┐рд╢реНрдЪрд┐рдд рдХрд░рдиреЗ рдХрд╛ рдкреНрд░рдпрд╛рд╕ рдХрд░реЗрдВрдЧреЗ рдХрд┐ рдкрд┐рдЫрд▓реЗ рдЕрдиреБрднрд╛рдЧ рдореЗрдВ рдкреНрд░рд╛рдкреНрдд рдХреЛрдбрд╛рдВрддрд░рдХ рдХреЛрдб рд╕рд╣реА рд╣реИред


рдЪреВрдВрдХрд┐ рд╣рдорд╛рд░реЗ рдкрд╛рд╕ рдкрд╣рд▓реЗ рд╕реЗ рд╣реА рдПрдХ рд╕рдВрдХрд▓рд┐рдд рдмрд╛рдЗрдирд░реА рд╣реИ, рдЖрдк рдЧреЛ рдХреЗ рд╕рд╛рде рдЖрдкреВрд░реНрддрд┐ рдХреА рдЧрдИ objdump рдЙрдкрдпреЛрдЧ рдХрд░ рд╕рдХрддреЗ рд╣реИрдВ:


 $ go tool objdump -s 'add1' exe TEXT main.add1(SB) example.go example.go:15 0x4bb760 488b442408 MOVQ 0x8(SP), AX example.go:15 0x4bb765 48ffc0 INCQ AX example.go:15 0x4bb768 4889442410 MOVQ AX, 0x10(SP) example.go:15 0x4bb76d c3 RET 

рд╕рдм рдХреБрдЫ рдкрд░рд┐рд╡рд░реНрддрд┐рдд рд╣реЛрддрд╛ рд╣реИ, рдХреЗрд╡рд▓ рд╡рд╛рдХреНрдпрд╡рд┐рдиреНрдпрд╛рд╕ рдереЛрдбрд╝рд╛ рдЕрд▓рдЧ рд╣реИ, рдЬреЛ рдЕрдкреЗрдХреНрд╖рд┐рдд рд╣реИред


рд╡рд┐рдзрд┐ рдХреЗ рднрд╛рд╡


рдпрджрд┐ рд╣рдореЗрдВ рд╡рд┐рдзрд┐рдпреЛрдВ рдХреЗ рд╕рд╛рде рдРрд╕рд╛ рдХрд░рдиреЗ рдХреА рдЖрд╡рд╢реНрдпрдХрддрд╛ рд╣реИ, рддреЛ рдлрд╝рдВрдХреНрд╢рди рдирд╛рдо рдХреЗ рдмрдЬрд╛рдп рд╣рдо рд╡рд┐рдзрд┐ рдЕрднрд┐рд╡реНрдпрдХреНрддрд┐ рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░реЗрдВрдЧреЗред


рдорд╛рди рд▓реЗрдВ рдХрд┐ рд╣рдорд╛рд░рд╛ add1 рд╡рд╛рд╕реНрддрд╡ рдореЗрдВ рдПрдХ рдлрд╝рдВрдХреНрд╢рди рдирд╣реАрдВ рд╣реИ, рд▓реЗрдХрд┐рди рдПрдХ add1 рдЯрд╛рдЗрдк рд╡рд┐рдзрд┐ рд╣реИ:


 type adder struct{} func (adder) add1(x int) int { return x + 2 } 

рддрдм рдлрд╝рдВрдХреНрд╢рди рдХрд╛ рдкрддрд╛ рдкреНрд░рд╛рдкреНрдд рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП рдХреЙрд▓ funcAddr(adder.add1) рддрд░рд╣ funcAddr(adder.add1) рджреЗрдЧрд╛ред


рдирд┐рд╖реНрдХрд░реНрд╖


рдореИрдВ рджреБрд░реНрдШрдЯрдирд╛ рд╕реЗ рдирд╣реАрдВ рдЗрди рдЪреАрдЬреЛрдВ рдХреЗ рд▓рд┐рдП рдЖрдпрд╛ рдерд╛ рдФрд░, рд╢рд╛рдпрдж, рдирд┐рдореНрдирд▓рд┐рдЦрд┐рдд рд▓реЗрдЦреЛрдВ рдореЗрдВ рд╕реЗ рдПрдХ рдореЗрдВ рдореИрдВ рдЖрдкрдХреЛ рдмрддрд╛рдКрдВрдЧрд╛ рдХрд┐ рдЗрди рд╕рднреА рддрдВрддреНрд░реЛрдВ рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рдиреЗ рдХреА рдпреЛрдЬрдирд╛ рдХреИрд╕реЗ рдмрдирд╛рдИ рдЧрдИ рдереАред рдЗрд╕ рдмреАрдЪ, рдореИрдВ рдЗрд╕ рд▓реЗрдЦ рдХреЛ рдЗрд╕ рдмрд╛рдд рдХрд╛ рд╕рддрд╣реА рд╡рд░реНрдгрди рдХрд░рдиреЗ рдХрд╛ рдкреНрд░рд╕реНрддрд╛рд╡ рдХрд░рддрд╛ рд╣реВрдВ рдХрд┐ runtime рдФрд░ рдлрдВрдХреНрд╢рди рд╡реИрд▓реНрдпреВ рдХреЗ рдорд╛рдзреНрдпрдо рд╕реЗ рд╣рдорд╛рд░реЗ рдЧреЛ рдлрд╝рдВрдХреНрд╢рдВрд╕ reflect рдХреИрд╕реЗ reflect ред


рдкреНрд░рдпреБрдХреНрдд рд╕рдВрд╕рд╛рдзрдиреЛрдВ рдХреА рд╕реВрдЪреА:


Source: https://habr.com/ru/post/hi482392/


All Articles