Network Security Internet Technology Development Database Servers Mobile Phone Android Software Apple Software Computer Software News IT Information

In addition to Weibo, there is also WeChat

Please pay attention

WeChat public account

Shulou

How to use go tool objdump

2025-03-01 Update From: SLTechnology News&Howtos shulou NAV: SLTechnology News&Howtos > Internet Technology >

Share

Shulou(Shulou.com)06/01 Report--

This article mainly explains "how to use go tool objdump". Friends who are interested might as well take a look. The method introduced in this paper is simple, fast and practical. Now let the editor take you to learn how to use go tool objdump.

1. With go tool objdump, you can see the machine code, assembly instructions, and offsets of any function. (there is a cmd/internal/goobj package under the go source code, you can read the redirection information of the .o file, even better. )

two。 Modify the relative jump of the internal functions of golang to point to the address of the same function of the loader (you can still see the initial address of the function with go tool objdump). Common runtime functions such as runtime.newobject, runtime.convT2Eslice, runtime.panicindex, runtime.morestack_noctxt, etc.

3. Modify the golang type pointer offset (a type pointer is required when the object is converted to interface {}) to point to the same type of loader.

4. Modify the offset that points to strings, global variables, and custom functions (usually relative offsets).

5. Write to mmap and execute.

The overall idea is to reuse the functions used by the loader, golang internal functions, golang type information, etc., by modifying the offset.

Disadvantages:

1. You can customize types, but you cannot assign objects of these types to interface {} (types already defined by the loader can), such as printing these objects using fmt.Println (but you can print the members of these objects). Because some global variables within golang (such as the golang type) may have pointers and are initialized from the beginning.

two。 Global variables cannot be initialized outside the function. Possible solution: define an entry function, initialize it, or read the main.init function and take out the initialization code. )

Advantages:

Still use the golang and golang compilation tools.

The speed is extremely fast, the body is small. It is equivalent to reusing golang internal scheduler, memory allocator, type system, and so on.

Can be customized. The assembly within the golang function is simple enough to develop your own tools to implement the above ideas.

The essence of golang is the scheduling implemented by three entities of GPM.

G corresponds to each task, P corresponds to each processor concept (that is, it contains a bunch of G, for example, execute G1 first, execute G2) M corresponds to system thread, M (including concepts such as system stack, etc.) binds a P, and then starts to run the G in P one by one.

The most basic flow chart is given by rain marks.

Behind the rain marks for the explanation of the three GPM is also in place. I don't plagiarize here.

two。 Initialization

The first introduction is that schedinit () is mainly the procresize function.

This procresize () adjusts the number of Ps in the system. Generally speaking, it is the number of cpu cores of the system, and the principle of more retreat and less compensation is also implemented during initialization, but you should pay attention to whether the exited P contains the current P, if so, you need to deal with a lot of details.

There is also a management structure for all P

Var allp [_ MaxGomaxprocs + 1] * p

Type schedt struct {

Pidle puintptr / / P

Npidle uint32 / / P

}

There is also a hint that if you call and modify runtime.GOMAXPROCS manually, it will cause stopTheWorld and startTheWorld, which themselves are relatively time-consuming, and then procresize () executed in startTheWorld is also more time-consuming.

3. Task Gripp

Hold up a chestnut first, pass

Go build-o test test.go

Go tool objdump-s "main\ .main" test

Go add (x, y) will be compiled into something similar

CALL runtime.newproc (SB)

This kind of code

Then I went to runtime to find it.

Newproc (after obtaining important information such as pc/ip address and input parameters)-> newproc1

After that, the data structure of G

Type g struct {

Stack stack / / execution stack

Sched gobuf / / is used to save the execution site

Goid int64 / / unique serial number

Gopc uintptr / / Caller PC/IP

Startpc uintptr / / task function

}

Newproc1 starts with all kinds of processing to create G, test G, align addresses, copy stacks, and save all kinds of chores on the spot. And then a runqput (p, newg, true) is put in by put.

It is possible for runqput to use g as a P.runnext, put it at the end, or throw it into the global queue.

The logic of g through p and then secondary cache reuse is slightly introduced, similar to the practice of cache/object,central. Correspond to two functions gfget and gfput respectively.

All g also has a global application allgs/allg, which is used to index all G for convenient recycling and shrinkstack.

Added a detail that only the local P queue will be dropped to the global queue when it is full, and it will lose half of the length of the local queue at a time to ensure efficiency and multi-core uniform scheduling.

4. Thread M

When the runqput is over, the wakep begins

Wake- > startm- > newm create / or notewakeup (& mp.park)

Newm- > newosproc- > linux call

Clone (cloneFlags,stk,unsafe.Pointer (mp), unsafe.Pointer (mp.g0), unsafe.Pointer (funcPC (mstart) starts the system thread, and the entry function is mstart

All m will be added to the allm linked list, will not be released, more than 10000 crash.

Finally, I added two details: 1 the mput&mget is also reused, and the mput&mget uses a level 1 cache.

Then said not to create too many m ah, time.Sleep is better than C.sleep (1), and so on.

5. Execution

When newm is mentioned above, the system thread is registered and mstart is used as the entry function.

And then we'll talk about mstart here.

Mstart->

Mstart1 aquirep binding p->

Schedule () takes into account all kinds of chores such as helping garbage collection tags, findrunable,- >

Call execute- >

Various ready stack JMP entry function entry address PC- >

After various calls are completed, the RET instruction restores the pre-pressed goexit address to PC/IP- >

Return G to the taking list->

Re-schedule ()

Then it introduces the backbone of findrunable:

1. Get the local P things through runqget.

2.globrunqget

3. Check the netpoll task

4. Try to steal other P's tasks. (Work-Stealing algorithm based on CAS and atomicset)

...

5. After that, various attempts will be made, and if there is no stopm, it will be done.

Lockedg

This is a specific invocation of cgo, binding the current g and m, and releasing it only at the end of the call.

An m is calling schedule () and will take a break if it is found to be bound by a G. If you find that the G you are about to call is bound by another m, it will wake it up and sleep on its own.

So each cgo routine has its own G call before the call is completed. Cgo therefore produces a large number of m.

At this point, I believe you have a deeper understanding of "how to use go tool objdump". You might as well do it in practice. Here is the website, more related content can enter the relevant channels to inquire, follow us, continue to learn!

Welcome to subscribe "Shulou Technology Information " to get latest news, interesting things and hot topics in the IT industry, and controls the hottest and latest Internet news, technology news and IT industry trends.

Views: 0

*The comments in the above article only represent the author's personal views and do not represent the views and positions of this website. If you have more insights, please feel free to contribute and share.

Share To

Internet Technology

Wechat

© 2024 shulou.com SLNews company. All rights reserved.

12
Report