How to get the actual address of the method?

I am trying to find the actual address of the method MyMethod of type MyType, but I ran into a small (big) problem.

package main

import (
    "fmt"
    "reflect"
)

type MyType struct{}

func (MyType) MyMethod(string) int {
    return 0
}

func main() {
    myType := reflect.TypeOf(MyType{})

    myMethod := myType.Method(0)

    fmt.Printf("%#v\n", myMethod) // first print

    fmt.Printf("%p\n", MyType.MyMethod) // second print

    myPointer := myType.Method(0).Func.Pointer()

    fmt.Printf("%#v\n", myPointer) // third print
}

Using the “reflect” standard package I obtained representation of MyMethod and placed it in the myMethod variable. Printing that variable yields the following (marked with the “first print” comment):

reflect.Method{Name:"MyMethod", PkgPath:"", Type:(*reflect.rtype)(0xcbc240), Func:reflect.Value{typ:(*reflect.rtype)(0xcbc240), ptr:(unsafe.Pointer)(0xc00000a048), flag:0x13}, Index:0}

It looks like ptr has an address I’m looking for, but when I enter the definition of reflect.Value, comment for ptr is:

// Pointer-valued data or, if flagIndir is set, pointer to data.
// Valid when either flagIndir is set or typ.pointers() is true.

It looks like the address 0xc00000a048 is valid (is the result of my searching) only if the flag flagIndir is set. So my sub question would be how to see if it’s set or not? Also, what does “pointer-valued data” mean?

Since I couldn’t find whether the given flag was set or not, I tried another way to reach the goal. The next thing I tried was to print the address of the method directly (marked with the “second print” comment). The print result completely confused me as it was completely different from the one with ptr (0xc00000a048). The print produced the following output: 0xcacf80.

Finally, I also tried to get the ptr directly and I did it (at least I think I did) and put the value in the myPointer variable. Printing the myPointer value only increased my confusion (marked with the “third print” comment). The printed value was again different from the one from ptr (0xc00000a048) but was the same as the one from the second printout. So I got the following: 0xcacf80.

By reading the comment related to Func.Pointer() I found this:

If v’s Kind is Func, the returned pointer is an underlying code pointer, but not necessarily enough to identify a single function uniquely. The only guarantee is that the result is zero if and only if v is a nil func Value.

It looks like this function does not have anything with the ptr and the address of the method? So, one more sub question is: Does it mean that function Pointer() does not return ptr but something else?

Would be nice if someone of you also answer on sub question, but my main and most important question is: How to get the actual (“real”) address of the method?

1 Like

Hi!

  1. The “real” address is impossible to get, indeed you can only get one code pointer, the pointer to the code of the function in memory which is calculated once. A function can be split into one or more code fragments each of which has its own code pointer, right? And from what I see in the source Go code of runtime package the code pointer you get is the last assigned by the PC at runtime so…It’s impossible to detect a single unique method pointer when a function is split in memory into two or more code fragments. At least at this abstraction level I think…

This is a bit bad explained…

It returns the ptr yes, at least the last code pointer. It’s correct.