Objdump

  1. Objdump Symbol Table
  2. Objdump Output
  3. Objdump Example

The objdump utility displays information about one or more object files. The options control what particular information to display. Arguments identify the object files to be examined. When you specify archives, objdump shows information on each of the member object files.

  • Objdump displays information about one or more object files. The options control what particular information to display. This information is mostly useful to programmers who are working on the compilation tools, as opposed to programmers who just want their program to compile and work. Are the object files to be examined.
  • See full list on linux.die.net.
  • And disassemble it with objdump d You should be able to get the exact byte from CSCI UA 201 at New York University.
  • According to its manpage, objdump is used to dsplay information from object files. It has a whole host of different switches that you can supply to interrogate object files, but we’ll only have a very simple usage for it in this post. I prefer Intel assembly syntax, so I’ll specify -M intel.

One of the most common bugs that you may encounter in go are race conditions. This is often the case when working with goroutines and non-atomic data types. Plenty of articles have covered goroutine race conditions, but why don’t we take another look and, this time, debug a couple race conditions to death by looking at what happens under the hood?

Let’s take a look at a typical example. We will examine what happens when we dereference a method receiver and assign it an object that we later modify. First, we will set up a couple structs:

Now we are going to create a method that returns an array of students.

Options

Let’s write a method for the Student struct. This method takes a pointer to a student and copies it to itself (the receiver):

We are now ready to test our race condition:

The process is straightforward, and it is explained in the comments. The method student.SetStudent should set the student to Abed. We then decide to overwrite the first student from our coolStudents array to Troy. We should expect that the student struct is set to Abed, but we get different results:

Instead of printing Abed as the student, we get Troy. We set Student to Abed, never to Troy, so what happened? In a nutshell, the method student.SetStudent is called asynchronously, and it does not get a chance to use coolStudents[0] before it gets updated in the next line. This may be a sufficient explanation, but let’s take a look at what is actually happening.

We will start by taking a closer look at student.SetStudent:

In the method, we dereference the student s (the method’s receiver), setting it to the value pointed by the student argument. Let’s take a look at what that looks like in go assembly (I did say we were going to debug this thing to death):

Objdump

Now, that is a lot of instructions for what seems like a simple operation. However, the revelant part occurs here:

First, go checks whether the garbage collector is busy to perform the copy operation, in which case it asks it to do so by calling runtime.typedmemmove, otherwise, the method itself performs the copy operation. Now let’s take a look at runtime.typedmemmove in the go source, found here:

Objdump Symbol Table

According to the comments, a race condition may occur given that, while the GC is creating a write barrier on the source object, another operation may change it. By the time the write barrier is created, and before the copy operation occurs, the src, which is passed to typedmemmove as an unsafe pointer, may be overwritten. This is exactly what happened in our case. That is, coolStudents[0] = coolStudents[1] overwrites src before student.SetStudent finishes the copy operation *s = *student.

Now let’s see what happens if instead we create a copy of the source student that we want to assing to our student struct by using this method instead, which also avoids dereferencing student:

When we call the above, we get the expected result:

Eventhough we are still overwriting coolStudents[0] with coolStudents[1] after calling CopyStudent as a goroutine, coolStudents[0] is copied when passed to CopyStudent, as it is passed by value. Furthermore we are not dereferencing student, so runtime.typedmemmove is never called, as shown in the go dissembly of the CopyStudent function:

Even though more instructions are required, we are no longer changing the src, and the write barriers can be created either by the GC or the function itself on the student object. We fixed the bug. However, CopyStudent has a lot more code. A better solution would be to use sync.Mutex, but we will examine that futher in future blog posts.

There are many ways to update an embedded system in the field. Images can fly through the air one a time, travel by sneaker or hitch a ride on other passing data. OK, maybe that’s a stretch, but there are certainly a plethora of ways to get those sweet update bytes into a target system. How are those bytes assembled, and what are the tools that do the assembly? This is the problem I needed to solve.

Objdump Output

Objdump

Objdump Example

Recall, my system wasn’t a particularly novel one (see the block diagram below). Just a few computers asking each other for an update over some serial busses. I had chosen to bundle the payload firmware images into the binary for the intermediate microcontroller which was to carry out the update process. The additional constraint was that the blending of the three firmware images (one carrier and two payload) needed to happen long after compile time, on a different system with a separate toolchain. There were ultimately two options that fit the bill.