When to Use --Dynamic Option in Nm

Why does the nm tool output for the extern-only and defined-only options overlap?

You're confusing -extern-only with -undefined-only.

There are two concepts that are being mixed here:

  • extern vs. local (in C extern vs. static, "local" is sometimes also called "private")
  • defined vs. undefined

The former describes the availability of a symbol while the latter describes its origin. And yes, even the notion of a private undefined symbol exists, as per man nm:

Each symbol name is preceded by its value (blanks if undefined). [...] A lower case u in a dynamic shared library indicates a undefined reference to a private external in another module in the same library.

Now, when using -undefined-only you actually do get the complement of -undefined-only

bash$ nm test.dylib 
0000000000000f60 T _derp
0000000000000f70 t _herp
U _printf
U dyld_stub_binder
bash$ nm -defined-only test.dylib 
0000000000000f60 T _derp
0000000000000f70 t _herp
bash$ nm -undefined-only test.dylib 
_printf
dyld_stub_binder
bash$ nm -extern-only test.dylib 
0000000000000f60 T _derp
U _printf
U dyld_stub_binder

-extern-only does not seem to have a complementary flag however.

File format differences between a static library (.a) and a shared library (.so)?

A static library, e.g. libfoo.a is not an executable of any kind.
It is simply an indexed archive in unix ar format
of other files which happen to be ELF
object files.

A static library is created like any archive:

ar crs libfoo.a objfile0.o objfile1.0...objfileN.o

outputs the new archive (c) libfoo.a, with those object files inserted (r)
and index added (s).

You'll hear of linking libfoo.a in a program. This doesn't mean that
libfoo.a itself is linked into or with the program. It means that libfoo.a
is passed to the linker as an archive from which it can extract and link into
the program just those object files within the archive that the program needs.
So the format of a static libary (ar format) is just an object-file
bundling format for linker input: it could equally well have been some other bundling
format without any effect on the linker's mission, which is to digest a set of
object files and shared libraries and generate a program, or shared library,
from them. ar format was history's choice.

On the other hand a shared library, e.g. libfoo.so, is an ELF file
and not any sort of archive.

Don't be tempted to suspect that a static library is a sort of ELF file by
the fact that all the well-known ELF-parsers - objdump, readelf, nm -
will parse a static libary. These tools all know that a static library is
an archive of ELF object files, so they just parse all the object files
in the library as if you had listed them on the commandline.

The use of the -D option with nm just instructs the tool to select
only the symbols that are in the dynamic symbol table(s), if any,
of the ELF file(s) that it parses - the symbols visible to the runtime linker
- regardless of whether or not they are parsed from within an archive. It's
the same as objdump -T and readelf --dyn-syms. It is not
necessary to use these options to parse the symbols from a shared library. If
you don't do so, then by default you'll just see the full symbol table.
If you run nm -D on a static library you'll be told no symbols, for
each object file in the archive - likewise if you ran nm -D for each of
those object files individually. The reason for that is that an object file
hasn't got a dynamic symbol table: only a shared library or progam has one.

Object file, shared library and program are all variants of the ELF format.
If you're interested in ELF variants, those are the variants of interest.

The ELF format itself is a long and thorny technical read and is required
background for precisely distinguishing the variants. Intro: An ELF file
contains a ELF header structure one of whose fields contains a type-identifier
of the file as an object file, shared library, or program. When the file is a
program or shared library, it also contains an optional Program header table
structure
whose fields provide the runtime linker/loader with the parameters
it needs to load the file in a process. In terms of ELF structure,
the differences between a program and a shared library are slight: it's
the detailed content that makes the difference to the behaviour that they
elicit from the loader.

For the long and thorny technical read, try Excutable and Linkable Format (ELF)

nm vs readelf -s

why nm give no result for striped libtest.so

There are two symbol tables in the original libtest.so: a "regular" one (in .symtab and .strtab sections) and a dynamic one (in .dynsym and .dynstr sections).

If strip removed both symbol tables, you library would be completely useless: the dynamic loader couldn't resolve any symbols in it. So strip does the only thing that makes sense: removes the "regular" symbol table, leaving the dynamic one intact.

You can see symbols in the dynamic symbol table with nm -D or readelf -s.

The "regular" symbol table is useful only for debugging (for example, it contains entries for static functions, which are not exported by the library, and do not show up in the dynamic symbol table).

But the dynamic loader never looks at the "regular" symbol table (which is not in a format suitable for fast symbol lookups); only at the dynamic one. So the "regular" symbol table is not needed for correct program operation, but the dynamic one is.

Why nm libc.so reports no symbols?

By default, nm reads the .symtab section in ELF objects, which is optional in non-relocatable objects. With the -D/--dynamic option, you can instruct nm to read the dynamic symbol table (which are the symbols actually used at run time). You may also want to use --with-symbol-versions because glibc uses symbol versioning extensively.

Alternatively, you can use eu-readelf --symbols=.dynsym or objdump -Tw. (readelf -sDW does not include symbol versioning information.)

How do I list the symbols in a .so file

The standard tool for listing symbols is nm, you can use it simply like this:

nm -gD yourLib.so

If you want to see symbols of a C++ library, add the "-C" option which demangle the symbols (it's far more readable demangled).

nm -gDC yourLib.so

If your .so file is in elf format, you have two options:

Either objdump (-C is also useful for demangling C++):

$ objdump -TC libz.so

libz.so: file format elf64-x86-64

DYNAMIC SYMBOL TABLE:
0000000000002010 l d .init 0000000000000000 .init
0000000000000000 DF *UND* 0000000000000000 GLIBC_2.2.5 free
0000000000000000 DF *UND* 0000000000000000 GLIBC_2.2.5 __errno_location
0000000000000000 w D *UND* 0000000000000000 _ITM_deregisterTMCloneTable

Or use readelf:

$ readelf -Ws libz.so
Symbol table '.dynsym' contains 112 entries:
Num: Value Size Type Bind Vis Ndx Name
0: 0000000000000000 0 NOTYPE LOCAL DEFAULT UND
1: 0000000000002010 0 SECTION LOCAL DEFAULT 10
2: 0000000000000000 0 FUNC GLOBAL DEFAULT UND free@GLIBC_2.2.5 (14)
3: 0000000000000000 0 FUNC GLOBAL DEFAULT UND __errno_location@GLIBC_2.2.5 (14)
4: 0000000000000000 0 NOTYPE WEAK DEFAULT UND _ITM_deregisterTMCloneTable

How to send dynamic option text and value using jquery and php

You mean

<td>
<select class="mySelect">
<option value="">Select</option>
<option value="100">Item-1</option>
<option value="200">Item-2</option>
<option value="300">Item-3</option>
<option value="400">Item-4</option>
<option value="500">Item-5</option>
</select>
<input type="hidden" class="descr" name="DESCRP[]" />
</td>
<td> <input type="text" class="amount" name="ALAMT[]"></td>

using

$('#myTable').on('change', '.mySelect', function() {
$(this).closest('tr').find('.amount').val($(this).val());
$(this).closest('tr').find('.descr').val($("option:selected",this).text());
});

How dynamic linking works, its usage and how and why you would make a dylib

When a C++ program is compiled. It needs to have references to the C++
library functions and code (say for example the code for the library).

Assume we have a hypothetical shared library called libdyno.so. You'll eventually be able to peek inside it using using objdump or nm.

objdump --syms libdyno.so

You can do this today on your system with any shared library. objdump on a MAC is called gobjdump and comes with brew in the binutils package. Try this on a mac...

gobjdump --syms /usr/lib/libz.dylib

You can now see that the symbols are contained in the shared object. When you link with the shared object you typically use something like

g++ -Wall -g -pedantic -ldyno DynoLib_main.cpp -o dyno_main

Note the -ldyno in that command. This is telling the compiler (really the linker ld) to look for a shared object file called libdyno.so wherever it normally looks for them. Once it finds that object it can then find the symbols it needs. There's no circular dependency because you the developer asked for the dynamic library to be loaded by specifying the -l flag.

How and when would you use a dynamic library? How do you make one? As in what
is the specific compiling command that is used to produce such a file from a
standard .cpp file

Create a file called DynoLib.cpp

#include "DynoLib.h"
DynamicLib::DynamicLib() {}
int DynamicLib::square(int a) {
return a * a;
}

Create a file called DynoLib.h

#ifndef DYNOLIB_H
#define DYNOLIB_H
class DynamicLib {
public:
DynamicLib();
int square(int a);
};
#endif

Compile them to be a shared library as follows. This is linux specific...

g++ -Wall -g -pedantic -shared -std=c++11 DynoLib.cpp -o libdyno.so

You can now inspect this object using the command I gave earlier ie

objdump --syms libdyno.so

Now create a file called DynoLib_main.cpp that will be linked with libdyno.so and use the function we just defined in it.

#include "DynoLib.h"    
#include <iostream>
using namespace std;
int main(void) {
DynamicLib *lib = new DynamicLib();
std::cout << "Square " << lib->square(1729) << std::endl;
return 1;
}

Compile it as follows

g++ -Wall -g -pedantic -L. -ldyno DynoLib_main.cpp -o dyno_main
./dyno_main
Square 2989441

You can also have a look at the main binary using nm. In the following I'm seeing if there is anything with the string square in it ie is the symbol I need from libdyno.so in any way referenced in my binary.

nm dyno_runner |grep square
U _ZN10DynamicLib6squareEi

The answer is yes. The uppercase U means undefined but this is the symbol name for our square method in the DynamicLib Class that we created earlier. The odd looking name is due to name mangling which is it's own topic.

How do I know which ones to link to statically as I would with a regular
.o file and which ones are supposed to be dynamically linked with?

You don't need to know. You specify what you want to link with and let the compiler (and linker etc) do the work. Note the -l flag names the library and the -L tells it where to look. There's a decent write up on how the compiler finds thing here

gcc Linkage option -L: Alternative ways how to specify the path to the dynamic library

Or have a look at man ld.

What are the -L and -l flags for? What does it mean to specify
for example a -lusb flag on the command line?

See the above link. This is from man ld..

-L searchdir

Add path searchdir to the list of paths that ld will search for
archive libraries and ld control scripts. You may use this option any
number of times. The directories are searched in the order in which
they are specified on the command line. Directories specified on the
command line are searched before the default directories. All -L
options apply to all -l options, regardless of the order in which the
options appear. -L options do not affect how ld searches for a linker
script unless -T option is specified.`

If you managed to get here it pays dividends to learn about the linker ie ld. It plays an important job and is the source of a ton of confusion because most people start out dealing with a compiler and think that compiler == linker and this is not true.



Related Topics



Leave a reply



Submit