unused DT entry: type 0x1d arg - android-ndk

I am using android NDK-r10d to build Android x86 executable (shared linking) that runs on adb shell. On run time, I am getting the following warning:
WARNING: linker: ./myapp: **unused DT entry:** type 0x1d arg 0x4a604
I am using a rooted Nexus Player to test the executable.
And my build machine is Ubuntu 14.04 (also tried on Fedora 14 machine).

What are "unused DT entry" errors?
If you have reached this page, it's probably because you have
compiled or attempted to run some binaries on your ARM based Android
system, with the result that your binary/app crashes or generates a
lot of warnings in your logcat. Typically something like this:
WARNING: linker: /blahblah/libopenssl.so: unused DT entry: type 0x6ffffffe arg 0x1188
Q: What is a "DT entry"?
In a few words, they are descriptive array entries in the file
structure of an ELF file. Specifically they are known as
Dynamic Array Tags and are requirements for executable and
shared objects. However, not all entries are required or available,
depending on the processor and kernel architecture.
In our case we are faced with a "Warning" that one of these are "unused".
What that means is, that your executable or library (*.so) files has been
compiled with the DT entry indicated, but your kernel is not supporting
that entry, for various reasons. The best examples are found on ARM based
Android systems, where the system library paths are fixed and the
cross compilers used for your firmware (OS/kernel) are set not to use
these entries. Usually the binaries still run just fine, but the kernel
is flagging this warning every time you're using it.
Q: When does this happen?
This can happen when:
Your ARM kernel is cross-compiled using the wrong flags (usually meant for other processor architectures).
Your ARM binaries and libraries are cross-compiled using AOS deprecated compilation flags.
and probably other ways yet to be discovered..
Starting from 5.1 (API 22) the Android linker warns about the VERNEED and
VERNEEDNUM ELF dynamic sections.
The most common flags that cause this error on Android devices are:
DT_RPATH 0x0f (15) The DT_STRTAB string table offset of a null-terminated library search path string.
This element's use has been superseded by DT_RUNPATH.
DT_RUNPATH 0x1d (29) The DT_STRTAB string table offset of a null-terminated library search path string.
DT_VERNEED 0x6ffffffe The address of the version dependency table. Elements within this table contain
indexes into the string table DT_STRTAB. This element requires that the
DT_VERNEEDNUM element also be present.
DT_VERNEEDNUM 0x6fffffff The number of entries in the DT_VERNEEDNUM table.
Tracking down the error above, we find that this message comes from the bionic library linker.cpp:
case DT_VERNEED:
verneed_ptr_ = load_bias + d->d_un.d_ptr;
break;
case DT_VERNEEDNUM:
verneed_cnt_ = d->d_un.d_val;
break;
case DT_RUNPATH:
// this is parsed after we have strtab initialized (see below).
break;
default:
if (!relocating_linker) {
DL_WARN("\"%s\" unused DT entry: type %p arg %p", get_realpath(),
reinterpret_cast<void*>(d->d_tag), reinterpret_cast<void*>(d->d_un.d_val));
}
break;
}
The code (above) supporting this symbol versioning was committed on April 9, 2015. Thus if your NDK build is either set to support API's earlier than this, or using build tools linking to this earlier library, you will get these warnings.
Q: How do I find what DT entries my system or binaries are using?
There are many ways to do this:
You look into your kernel sources for <linux/elf.h>.
You look in your Android NDK installation folders and check:
# To find all elf.h files:
find /<path_to>/ndk/platforms/android-*/arch-arm*/usr/include/linux/ -iname "elf.h"
Do an readelf of your binary:
$ readelf --dynamic libopenssl.so
Dynamic section at offset 0x23b960 contains 28 entries:
Tag Type Name/Value
0x00000003 (PLTGOT) 0x23ce18
0x00000002 (PLTRELSZ) 952 (bytes)
0x00000017 (JMPREL) 0x15e70
0x00000014 (PLTREL) REL
0x00000011 (REL) 0x11c8
0x00000012 (RELSZ) 85160 (bytes)
0x00000013 (RELENT) 8 (bytes)
0x6ffffffa (RELCOUNT) 10632
0x00000015 (DEBUG) 0x0
0x00000006 (SYMTAB) 0x148
0x0000000b (SYMENT) 16 (bytes)
0x00000005 (STRTAB) 0x918
0x0000000a (STRSZ) 1011 (bytes)
0x00000004 (HASH) 0xd0c
0x00000001 (NEEDED) Shared library: [libdl.so]
0x00000001 (NEEDED) Shared library: [libc.so]
0x0000001a (FINI_ARRAY) 0x238458
0x0000001c (FINI_ARRAYSZ) 8 (bytes)
0x00000019 (INIT_ARRAY) 0x238460
0x0000001b (INIT_ARRAYSZ) 16 (bytes)
0x00000020 (PREINIT_ARRAY) 0x238470
0x00000021 (PREINIT_ARRAYSZ) 0x8
0x0000001e (FLAGS) BIND_NOW
0x6ffffffb (FLAGS_1) Flags: NOW
0x6ffffff0 (VERSYM) 0x108c
0x6ffffffe (VERNEED) 0x1188
0x6fffffff (VERNEEDNUM) 2
0x00000000 (NULL) 0x0
As you can see from the error above, the type corresponds to DT_VERNEED.
From THIS document:
DT_RPATH
This element holds the string table offset of a null-terminated search
library search path string, discussed in "Shared Object Dependencies."
The offset is an index into the table recorded in the DT_STRTAB entry.
DT_RPATH may give a string that holds a list of directories, separated
by colons (:). All LD_LIBRARY_PATH directories are searched after
those from DT_RPATH.
Q: So how do you solve or deal with these issues?
There are essentially 3 ways to deal with this:
the quick
the bad
the ugly
The Quick (you don't have any sources or just can't be bothered)
Use an "ELF cleaner" to remove the offending DT entries from a all your binaries. This is an easy and quick remedy, especially when you don't have the sources to recompile them properly for your system. There are at least two cleaners out there that you can use.
The Bad (you have the sources)
Is the right way to do it, because you'll become a bad-ass ARM cross compiler guru in the process of getting it to work. You basically need to find and tune the compiler settings in the Makefiles used.
From here:
The Android linker (/system/bin/linker) does not support RPATH or RUNPATH, so we set LD_LIBRARY_PATH=$USR/lib and try to avoid building useless rpath entries with --disable-rpath configure flags. Another option to avoid depending on LD_LIBRARY_PATH would be supplying a custom linker - this is not done due to the overhead of maintaining a custom linker.
The Ugly (You just want your app to work with any dirty binary.)
You tell your Java app not to freak out when checking for null
in error handlers and instead get fed these warnings, possibly
causing fatal exceptions. Use something like:
class OpensslErrorThread extends Thread {
#Override
public void run() {
try {
while(true){
String line = opensslStderr.readLine();
if(line == null){
// OK
return;
}
if(line.contains("unused DT entry")){
Log.i(TAG, "Ignoring \"unused DT entry\" error from openssl: " + line);
} else {
// throw exception!
break;
}
}
} catch(Exception e) {
Log.e(TAG, "Exception!")
}
}
}
This is very bad and ugly as it doesn't solve anything, while bloating your code. In addition, the warnings are there for a reason, and that is that in future AOS versions, this will become a full fledged error!
Q. What else?
Many changes in the API's between 18-25 (J to N) has been made in
way the Android kernel and libraries are compiled. I cannot
provide a remotely close explanation of all that, but perhaps this
will help guide you in the right direction. The best sources is
of course looking in the Android sources and documentation itself.
For example, HERE or HERE.
And finally the full list:
Name Value d_un Executable Shared Object
---------------------------------------------------------------------------------------------
DT_NULL 0 Ignored Mandatory Mandatory
DT_NEEDED 1 d_val Optional Optional
DT_PLTRELSZ 2 d_val Optional Optional
DT_PLTGOT 3 d_ptr Optional Optional
DT_HASH 4 d_ptr Mandatory Mandatory
DT_STRTAB 5 d_ptr Mandatory Mandatory
DT_SYMTAB 6 d_ptr Mandatory Mandatory
DT_RELA 7 d_ptr Mandatory Optional
DT_RELASZ 8 d_val Mandatory Optional
DT_RELAENT 9 d_val Mandatory Optional
DT_STRSZ 0x0a (10) d_val Mandatory Mandatory
DT_SYMENT 0x0b (11) d_val Mandatory Mandatory
DT_INIT 0x0c (12) d_ptr Optional Optional
DT_FINI 0x0d (13) d_ptr Optional Optional
DT_SONAME 0x0e (14) d_val Ignored Optional
DT_RPATH 0x0f (15) d_val Optional Optional
DT_SYMBOLIC 0x10 (16) Ignored Ignored Optional
DT_REL 0x11 (17) d_ptr Mandatory Optional
DT_RELSZ 0x12 (18) d_val Mandatory Optional
DT_RELENT 0x13 (19) d_val Mandatory Optional
DT_PLTREL 0x14 (20) d_val Optional Optional
DT_DEBUG 0x15 (21) d_ptr Optional Ignored
DT_TEXTREL 0x16 (22) Ignored Optional Optional
DT_JMPREL 0x17 (23) d_ptr Optional Optional
DT_BIND_NOW 0x18 (24) Ignored Optional Optional
DT_INIT_ARRAY 0x19 (25) d_ptr Optional Optional
DT_FINI_ARRAY 0x1a (26) d_ptr Optional Optional
DT_INIT_ARRAYSZ 0x1b (27) d_val Optional Optional
DT_FINI_ARRAYSZ 0x1c (28) d_val Optional Optional
DT_RUNPATH 0x1d (29) d_val Optional Optional
DT_FLAGS 0x1e (30) d_val Optional Optional
DT_ENCODING 0x1f (32) Unspecified Unspecified Unspecified
DT_PREINIT_ARRAY 0x20 (32) d_ptr Optional Ignored
DT_PREINIT_ARRAYSZ 0x21 (33) d_val Optional Ignored
DT_MAXPOSTAGS 0x22 (34) Unspecified Unspecified Unspecified
DT_LOOS 0x6000000d Unspecified Unspecified Unspecified
DT_SUNW_AUXILIARY 0x6000000d d_ptr Unspecified Optional
DT_SUNW_RTLDINF 0x6000000e d_ptr Optional Optional
DT_SUNW_FILTER 0x6000000e d_ptr Unspecified Optional
DT_SUNW_CAP 0x60000010 d_ptr Optional Optional
DT_SUNW_SYMTAB 0x60000011 d_ptr Optional Optional
DT_SUNW_SYMSZ 0x60000012 d_val Optional Optional
DT_SUNW_ENCODING 0x60000013 Unspecified Unspecified Unspecified
DT_SUNW_SORTENT 0x60000013 d_val Optional Optional
DT_SUNW_SYMSORT 0x60000014 d_ptr Optional Optional
DT_SUNW_SYMSORTSZ 0x60000015 d_val Optional Optional
DT_SUNW_TLSSORT 0x60000016 d_ptr Optional Optional
DT_SUNW_TLSSORTSZ 0x60000017 d_val Optional Optional
DT_SUNW_CAPINFO 0x60000018 d_ptr Optional Optional
DT_SUNW_STRPAD 0x60000019 d_val Optional Optional
DT_SUNW_CAPCHAIN 0x6000001a d_ptr Optional Optional
DT_SUNW_LDMACH 0x6000001b d_val Optional Optional
DT_SUNW_CAPCHAINENT 0x6000001d d_val Optional Optional
DT_SUNW_CAPCHAINSZ 0x6000001f d_val Optional Optional
DT_HIOS 0x6ffff000 Unspecified Unspecified Unspecified
DT_VALRNGLO 0x6ffffd00 Unspecified Unspecified Unspecified
DT_CHECKSUM 0x6ffffdf8 d_val Optional Optional
DT_PLTPADSZ 0x6ffffdf9 d_val Optional Optional
DT_MOVEENT 0x6ffffdfa d_val Optional Optional
DT_MOVESZ 0x6ffffdfb d_val Optional Optional
DT_POSFLAG_1 0x6ffffdfd d_val Optional Optional
DT_SYMINSZ 0x6ffffdfe d_val Optional Optional
DT_SYMINENT 0x6ffffdff d_val Optional Optional
DT_VALRNGHI 0x6ffffdff Unspecified Unspecified Unspecified
DT_ADDRRNGLO 0x6ffffe00 Unspecified Unspecified Unspecified
DT_CONFIG 0x6ffffefa d_ptr Optional Optional
DT_DEPAUDIT 0x6ffffefb d_ptr Optional Optional
DT_AUDIT 0x6ffffefc d_ptr Optional Optional
DT_PLTPAD 0x6ffffefd d_ptr Optional Optional
DT_MOVETAB 0x6ffffefe d_ptr Optional Optional
DT_SYMINFO 0x6ffffeff d_ptr Optional Optional
DT_ADDRRNGHI 0x6ffffeff Unspecified Unspecified Unspecified
DT_RELACOUNT 0x6ffffff9 d_val Optional Optional
DT_RELCOUNT 0x6ffffffa d_val Optional Optional
DT_FLAGS_1 0x6ffffffb d_val Optional Optional
DT_VERDEF 0x6ffffffc d_ptr Optional Optional
DT_VERDEFNUM 0x6ffffffd d_val Optional Optional
DT_VERNEED 0x6ffffffe d_ptr Optional Optional
DT_VERNEEDNUM 0x6fffffff d_val Optional Optional
DT_LOPROC 0x70000000 Unspecified Unspecified Unspecified
DT_SPARC_REGISTER 0x70000001 d_val Optional Optional
DT_AUXILIARY 0x7ffffffd d_val Unspecified Optional
DT_USED 0x7ffffffe d_val Optional Optional
DT_FILTER 0x7fffffff d_val Unspecified Optional
DT_HIPROC 0x7fffffff Unspecified Unspecified Unspecified

With readelf -d you may list DT entries in your binary:
0x0000001d (RUNPATH) Library runpath: [lib]
As you may see, 0x1d corresponds to RUNPATH
That entry is added with linker option -rpath (or -R, if followed by directory)

Related

Is there a way to convert a string (ASCII) to Hex in CMake

Is there a way to convert a string (ASCII "a-z, A-Z, 0-9") to Hex in CMake?
For example (ASCII to hex):
"HELLO" --> 0x48 0x45 0x4C 0x4C 0x4F
Should be the opposite operation of the following command (see here):
string(ASCII <number> \[<number> ...\] <output variable>)
I tried some CMake math operations, but it didn't seem to work on strings.
I can implement a function with a big "if" that compares the char input of "a-z, A-Z, 0-9" and returns its hex according to the AsciiTable, but I am looking for a smarter/shorter solution.
EDIT: As of CMake 3.18, the inverse operation of string(ASCII ...) now exists. Use string(HEX ...):
set(TEST_STRING "HELLO")
# Convert the string to hex.
string(HEX ${TEST_STRING} HEX_STRING)
message(${HEX_STRING})
This prints the following:
48454c4c4f
so you have to manually add the 0x prefixes (which is described below in the response applicable for earlier CMake versions).
For CMake 3.17 and earlier, I am not aware of any support for ASCII to hex conversions that is native to CMake (i.e. the inverse operation for string(ASCII ... ) doesn't exist). One work-around is to leverage CMake's file() commands to write the ASCII to a file, then read it as hex. With some additional formatting using string(REGEX MATCHALL ...) and list(JOIN ...), we can get a string of hex values representing the ASCII inputs:
set(TEST_STRING "HELLO")
# Write the ASCII file, then read it as hex.
file(WRITE ${CMAKE_BINARY_DIR}/asciiToHexFile.txt "${TEST_STRING}")
file(READ ${CMAKE_BINARY_DIR}/asciiToHexFile.txt HEX_CONTENTS HEX)
message("HEX_CONTENTS: ${HEX_CONTENTS}")
# Separate into individual bytes.
string(REGEX MATCHALL "([A-Za-z0-9][A-Za-z0-9])" SEPARATED_HEX "${HEX_CONTENTS}")
message("SEPARATED_HEX: ${SEPARATED_HEX}")
# Append the "0x" to each byte.
list(JOIN SEPARATED_HEX " 0x" FORMATTED_HEX)
# JOIN misses the first byte's "0x", so add it here.
string(PREPEND FORMATTED_HEX "0x")
message("FORMATTED_HEX: ${FORMATTED_HEX}")
With the input HELLO, the output prints the following:
HEX_CONTENTS: 48454c4c4f
SEPARATED_HEX: 48;45;4c;4c;4f
FORMATTED_HEX: 0x48 0x45 0x4c 0x4c 0x4f
I ended up creating this function, based on #squareskittles response:
function(STRING_HEX_KEY_TO_C_BYTE_ARRAY STRING_HEX VARIABLE_NAME)
# Separate into individual bytes.
string(REGEX MATCHALL "([A-Fa-f0-9][A-Fa-f0-9])" SEPARATED_HEX ${STRING_HEX})
# Append the "0x" to each byte.
list(JOIN SEPARATED_HEX ", 0x" FORMATTED_HEX)
# Prepend "{ 0x"
string(PREPEND FORMATTED_HEX "{ 0x")
# Append " }"
string(APPEND FORMATTED_HEX " }")
set(${VARIABLE_NAME} ${FORMATTED_HEX} PARENT_SCOPE)
message(${VARIABLE_NAME}=${FORMATTED_HEX})
endfunction()
Use this function to convert string hex to C byte array, like this:
STRING_HEX_KEY_TO_C_BYTE_ARRAY("FFFF020200000030" "DEVICE_EUI")
Output message:
DEVICE_EUI={ 0xFF, 0xFF, 0x02, 0x02, 0x00, 0x00, 0x00, 0x30 }

USB HID Codes mystery

I'm currently writing out USB HID codes in Python 3....
NULL_CHAR = chr(0)
def write_report(report):
with open('/dev/hidg0', 'rb+') as fd:
fd.write(report.encode())
# Press SHIFT + a = A
write_report(chr(32)+NULL_CHAR+chr(4)+NULL_CHAR*5)
# Release all keys
write_report(NULL_CHAR*8)
My question:
By looking at the standard "USB HID Usage Tables" from USB.org ( v1.12 - 10-21-2004 - https://www.usb.org/document-library/hid-usage-tables-112 ) ...
I know from actively running the example above
( Using "USAGE ID" in Decimal FYI ), that CHR(32) is a < SHIFT >, but in the HID table it shows that a Decimal (32) is a Keyboard < 3 > or < # > ..
What's up with that ?
Am I using the wrong table, Should i be using ASCii codes instead of USB HID Keyboard codes ?
Is there a better/more accurate table of codes ?
Because if chr(32) is in reality a < SHIFT >, what then would be < 3 > ?
Is there an easier way to type Function Keys ( F1+F3+F5 ) in combination, in addition to full text lines, and issue them out over USB than the way i'm currently doing it ?
Any help to clear this up by the pro's here would be greatly appreciated !!!
Not sure if you still need the answer, but I figured out after a day of headache over the same thing.
The information you're sending always must be transferred as 8 bytes.
So from your example:
write_report(chr(32)+NULL_CHAR+chr(4)+NULL_CHAR*5)
The chr(32) is Byte 0 (which is the modifier), then comes a null char at Byte 1, then the actual char at Byte 2, then another 5 nullchars, to make it 8.
Modifiers follow a different system from actual chars.
LCTRL 0x01
LSHIFT 0x02
LALT 0x04
LMETA 0x08
RCTRL 0x10
RSHIFT 0x20
RALT 0x40
RMETA 0x80
So the reason for 32 is because that's the decimal equivalent of 0x20 in hex.
Hope this helps you, or anyone else looking for this answer.

How to get right MIPS libc toolchain for embedded device

I've run into a problem (repetitively) with various company's' embedded linux products where GPL source code from them does not match what is actually running on a system. It's "close", but not quite right, especially with respect to the standard C library they use.
Isn't that a violation of the GPL?
Often this mismatch results in a programmer (like me) cross compiling only to have the device reply cryptically "file not found" or something similar when the program is run.
I'm not alone with this kind of problem -- For many people have threads directly and indirectly related to the problem: eg:
Compile parameters for MIPS based codesourcery toolchain?
And I've run into the problem on Sony devices, D-link, and many others. It's very common.
Making a new library is not a good solution, since most systems are ROMFS only, and LD_LIBRARY_PATH is sometimes broken -- so that installing a new library on the device wastes very limited memory and often won't work.
If I knew what the right source code version of the library was, I could go around the manufacturer's carelessness and compile it from the original developer's tree; but how can I find out which version I need when all I have is the binary of the library itself?
For example: I ran elfread -a libc.so.0 on a DSL modem's libc (see below); but I don't see anything here that could tell me exactly which libc it was...
How can I find the name of the source code, or an identifier from the library's binary so I can create a cross compiler using that library? eg: Can anyone tell me what source code this library came from, and how they know?
ELF Header:
Magic: 7f 45 4c 46 01 02 01 00 00 00 00 00 00 00 00 00
Class: ELF32
Data: 2's complement, big endian
Version: 1 (current)
OS/ABI: UNIX - System V
ABI Version: 0
Type: DYN (Shared object file)
Machine: MIPS R3000
Version: 0x1
Entry point address: 0x5a60
Start of program headers: 52 (bytes into file)
Start of section headers: 0 (bytes into file)
Flags: 0x1007, noreorder, pic, cpic, o32, mips1
Size of this header: 52 (bytes)
Size of program headers: 32 (bytes)
Number of program headers: 4
Size of section headers: 0 (bytes)
Number of section headers: 0
Section header string table index: 0
There are no sections in this file.
There are no sections to group in this file.
Program Headers:
Type Offset VirtAddr PhysAddr FileSiz MemSiz Flg Align
REGINFO 0x0000b4 0x000000b4 0x000000b4 0x00018 0x00018 R 0x4
LOAD 0x000000 0x00000000 0x00000000 0x2c9ee 0x2c9ee R E 0x1000
LOAD 0x02c9f0 0x0006c9f0 0x0006c9f0 0x009a0 0x040b8 RW 0x1000
DYNAMIC 0x0000cc 0x000000cc 0x000000cc 0x0579a 0x0579a RWE 0x4
Dynamic section at offset 0xcc contains 19 entries:
Tag Type Name/Value
0x0000000e (SONAME) Library soname: [libc.so.0]
0x00000004 (HASH) 0x18c
0x00000005 (STRTAB) 0x3e9c
0x00000006 (SYMTAB) 0x144c
0x0000000a (STRSZ) 6602 (bytes)
0x0000000b (SYMENT) 16 (bytes)
0x00000015 (DEBUG) 0x0
0x00000003 (PLTGOT) 0x6ce20
0x00000011 (REL) 0x5868
0x00000012 (RELSZ) 504 (bytes)
0x00000013 (RELENT) 8 (bytes)
0x70000001 (MIPS_RLD_VERSION) 1
0x70000005 (MIPS_FLAGS) NOTPOT
0x70000006 (MIPS_BASE_ADDRESS) 0x0
0x7000000a (MIPS_LOCAL_GOTNO) 11
0x70000011 (MIPS_SYMTABNO) 677
0x70000012 (MIPS_UNREFEXTNO) 17
0x70000013 (MIPS_GOTSYM) 0x154
0x00000000 (NULL) 0x0
There are no relocations in this file.
The decoding of unwind sections for machine type MIPS R3000 is not currently supported.
Histogram for bucket list length (total of 521 buckets):
Length Number % of total Coverage
0 144 ( 27.6%)
1 181 ( 34.7%) 27.1%
2 130 ( 25.0%) 66.0%
3 47 ( 9.0%) 87.1%
4 12 ( 2.3%) 94.3%
5 5 ( 1.0%) 98.1%
6 1 ( 0.2%) 99.0%
7 1 ( 0.2%) 100.0%
No version information found in this file.
Primary GOT:
Canonical gp value: 00074e10
Reserved entries:
Address Access Initial Purpose
0006ce20 -32752(gp) 00000000 Lazy resolver
0006ce24 -32748(gp) 80000000 Module pointer (GNU extension)
Local entries:
Address Access Initial
0006ce28 -32744(gp) 00070000
0006ce2c -32740(gp) 00030000
0006ce30 -32736(gp) 00000000
0006ce34 -32732(gp) 00010000
0006ce38 -32728(gp) 0006d810
0006ce3c -32724(gp) 0006d814
0006ce40 -32720(gp) 00020000
0006ce44 -32716(gp) 00000000
0006ce48 -32712(gp) 00000000
Global entries:
Address Access Initial Sym.Val. Type Ndx Name
0006ce4c -32708(gp) 000186c0 000186c0 FUNC bad section index[ 6] __fputc_unlocked
0006ce50 -32704(gp) 000211a4 000211a4 FUNC bad section index[ 6] sigprocmask
0006ce54 -32700(gp) 0001e2b4 0001e2b4 FUNC bad section index[ 6] free
0006ce58 -32696(gp) 00026940 00026940 FUNC bad section index[ 6] raise
...
truncated listing
....
Note:
The rest of this post is a blog showing how I came to ask the question above and to put useful information about the subject in one place.
Don't bother reading it unless you want to know I actually did research the question... in gory detail... and how NOT to answer my question.
The proper (theoretical) way to get a libc program running on (for example) a D-link modem would simply be to get the TRUE source code for the product from the manufacturer, and compile against those libraries.... (It's GPL !? right, so the law is on our side, right?)
For example: I just bought a D-Link DSL-520B modem and a 526B modem -- but found out after the fact that the manufacturer "forgot" to supply linux source code for the 520B but does have it for the 526B. I checked all of the DSL-5xxB devices online for source code & toolchains, finding to my delight that ALL of them (including 526B) -- contain the SAME pre-compiled libc.so.0 with MD5sum of 6ed709113ce615e9f170aafa0eac04a6 . So in theory, all supported modems in the DSL-5xxB family seemed to use the same libc library... and I hoped I might be able to use that library.
But after I figured out how to get the DSL modem itself to send me a copy of the installed /lib/libc.so.0 library -- I found to my disgust that they ALL use a library with MD5 sum of b8d492decc8207e724a0822641205078 . In NEITHER of the modems I bought (supported or not) was found the same library as contained in the source code toolchain.
To verify the toolchain from D-link was defective, I didn't compile a program (the toolchain wouldn't run on my PC anyway as it was the wrong binary format) -- but I found the toolchain had some pre-compiled mips binaries in it already; so I simply downloaded one to the modem and chmod +x -- and (surprise) I got the message "file not found." when I tried to run it ... It won't run.
So, I knew the toolchains were no good immediately, but not exactly why.
I decided to get a newer verson of MIPS GCC (binary version) that should have less bugs, more features and which is supported on most PC platforms. This is the way to GO!
See: Kernel.org pre-compiled binaries
I upgraded to gcc 4.9.0 after selecting the older "mips" verson from the above site to get the right FTP page; and set my shells' PATH variable to the /bin directory of the cross compiler once installed.
Then I copied all the header files and libraries from the D-link source code package into the new cross compiler just to verify that it could compile D-link libc binaries. And it did on the first try, compiling "hello world!" with no warnings or errors into a mips 32 big endian binary.
( START EDIT: ) #ChrisStratton points out in the comments (after this post) that my test of the toolchain is inadequate, and that using a newer GCC with an older library -- even though it links properly -- is flawed as a test. I wish there was a way to give him points for his comments -- I've become convinced that he's right; although that makes what D-link did even a worse problem -- for there's no way to know from the binaries on the modem which GCC they actually used. The GCC used for the kernel isn't necessarily the same used in user space.
In order to test the new compiler's compatibility with the modems and also make tools so I could get a copy of the actual libraries found on the modem: ( END EDIT ) I wrote a program that doesn't use the C library at all (but in two parts): It ran just fine... and the code is attached to show how it can be done.
The first listing is an assembly language program to bypass linking the standard C libraries on MIPS; and the second listing is a program meant to create an octal number dump of a binary file/stream using only the linux kernel. eg: It enables copying/pasting or scripting of binary data over telnet, netcat, etc... via ash/bash or busybox :) like a poor man's uucp.
// substart.S MIPS assembly language bypass of libc startup code
// it just calls main, and then jumps to the exit function
.text
.globl __start
__start: .ent __start
.frame $29, 32, $31
.set noreorder
.cpload $25
.set reorder
.cprestore 16
jal main
j exit
.end __start
// end substart.S
...and...
// octdump.c
// To compile w/o libc :
// mips-linux-gcc stubstart.S octdump.c -nostdlib -o octdump
// To compile with working libc (eg: x86 system) :
// gcc octdump.c -o octdump_x86
#include <syscall.h>
#include <errno.h>
#include <sys/types.h>
int* __errno_location(void) { return &errno; }
#ifdef _syscall1
// define three unix functions (exit,read,write) in terms of unix syscall macros.
_syscall1( void, exit, int, status );
_syscall3( ssize_t, read, int, fd, void*, buf, size_t, count );
_syscall3( ssize_t, write, int, fd, const void*, buf, size_t, count );
#endif
#include <unistd.h>
void oct( unsigned char c ) {
unsigned int n = c;
int m=6;
static unsigned char oval[6]={'\\','\\','0','0','0','0'};
if (n < 64) { m-=1; n <<= 3; }
if (n < 64) { m-=1; n <<= 3; }
if (n < 64) { m-=1; n <<= 3; }
oval[5]='0'+(n&7);
oval[4]='0'+((n>>3)&7);
oval[3]='0'+((n>>6)&7);
write( STDOUT_FILENO, oval, m );
}
int main(void) {
char buffer[255];
int count=1;
int i;
while (count>0) {
count=read( STDIN_FILENO, buffer, 17 );
if (count>0) write( STDOUT_FILENO, "echo -ne $'",11 );
for (i=0; i<count; ++i) oct( buffer[i] );
if (count>0) write( STDOUT_FILENO, "'\n", 2 );
}
write( STDOUT_FILENO,"#\n",2);
return 0;
}
Once mips' octdump was saved (chmod +x) as /var/octdump on the modem, it ran without errors.
(use your imagination about how I got it on there... Dlink's TFTP, & friends are broken.)
I was able to use octdump to copy all the dynamic libraries off the DSL modem and examine them, using an automated script to avoid copy/pasting by hand.
#!/bin/env python
# octget.py
# A program to upload a file off an embedded linux device via telnet
import socket
import time
import sys
import string
if len( sys.argv ) != 4 :
raise ValueError, "Usage: octget.py IP_OF_MODEM passwd path_to_file_to_get"
o = socket.socket( socket.AF_INET, socket.SOCK_STREAM )
o.connect((sys.argv[1],23)) # The IP address of the DSL modem.
time.sleep(1)
sys.stderr.write( o.recv(1024) )
o.send("admin\r\n");
time.sleep(0.1)
sys.stderr.write( o.recv(1024) )
o.send(sys.argv[2]+"\r\n")
time.sleep(0.1)
o.send("sh\r\n")
time.sleep(0.1)
sys.stderr.write( o.recv(1024) )
o.send("cd /var\r\n")
time.sleep(0.1)
sys.stderr.write( o.recv(1024) )
o.send("./octdump.x < "+sys.argv[3]+"\r\n" );
sys.stderr.write( o.recv(21) )
get="y"
while get and not ('#' in get):
get = o.recv(4096)
get = get.translate( None, '\r' )
sys.stdout.write( get )
time.sleep(0.5)
o.close()
The DSL520B modem had the following libraries...
libcrypt.so.0 libpsi.so libutil.so.0 ld-uClibc.so.0 libc.so.0 libdl.so.0 libpsixml.so
... and I thought I might cross compile using these libraries since (at least in theory) -- GCC could link against them; and my problem might be solved.
I made very sure to erase all the incompatible .so libraries from gcc-4.9.0/mips-linux/mips-linux/lib, but kept the generic crt..o files; then I copied the modem's libraries into the cross compiler directory.
But even though the kernel version of the source code, and the kernel version of the modem matched -- GCC found undefined symbols in the crt files.... So, either the generic crt files or the modem libraries themselves are somehow defective... and I don't know why. Without knowing how to get the full library version of the ? ucLibc ? library, I'm not sure how I can get the CORRECT source code to recompile the libraries and the crt's from scratch.

ELF Header, are offset 06h and 14h duplicated?

I would like to know if these 2 headers have the same meaning nor why?
From wikipedia :
offset 06h : Set to 1 for the original version of ELF.
offset 14h : Set to 1 for the original version of ELF.
reference : http://en.wikipedia.org/wiki/Executable_and_Linkable_Format
You may want to read a more detailed document which is likely to include the information you're looking for:
http://www.skyfree.org/linux/references/ELF_Format.pdf
The header structure
#define EINIDENT 16
typedefstruct{
unsigned char e_ident[EINIDENT];
Elf32_Half e_type;
Elf32_Half e_machine;
Elf32_Word e_version;
Elf32_Addr e_entry;
Elf32_Off e_phoff;
Elf32_Off e_shoff;
Elf32_Word e_flags;
Elf32_Half e_ehsize;
Elf32_Half e_phentsize;
Elf32_Half e_phnum;
Elf32_Half e_shentsize;
Elf32_Half e_shnum;
Elf32_Half e_shstrndx;
} Elf32Ehdr;
The 2nd e_version which defines the version as 1 (i.e. "current")
e_version This member identifies the object file version.
Name Value Meaning
EV_NONE 0 Invalid version
EV_CURRENT 1 Current version
The value 1 signifies the original file format; extensions will
create new versions with higher numbers. The value of EV_CURRENT,
though given as 1 above, will change as necessary to reflect the
current version number.
The version in the e_ident part is also EV_CURRENT, so exactly the same version:
EI_VERSION Byte e_ident[EI_VERSION] specifies the ELF header version
number. Currently, this value must be EV_CURRENT, as
explained above for e_version.
From what I understand, I would say that the version has not changed yet so it is still 1 in both places, but that could change in the future...

error C2440: 'static_cast' : cannot convert from 'long' to 'LRESULT'

I am converting my project from a 32 bit version to 64 bit version, when compiling the project in 64 bit, i get the below error.
Error 2 error C2440: 'static_cast' : cannot convert from 'long (__cdecl BrnDefDlgClass::* )(UINT,long)' to 'LRESULT (__cdecl CWnd::* )(WPARAM,LPARAM)' C:\Program Files (x86)\...\CXX\TEST.CXX 854 1 cfg
this error points me to below line of code.
ON_MESSAGE (WM_USER_AFTERCBNSELCHANGE, OnAfterCBSelectMsg)
advice please why would this error occur.
Thanks
I suggest you look at the definition of OnAfterCBSelectMsg and modify it to use LRESULT as return type, and WPARAM and LPARAM as parameters (just as the second signature in your error message).
LRESULT is defined as LONG_PTR, and whenever PTR appears in a name, you should expect it to be large enough to hold a pointer. Pointers are 4 bytes on 32 Bit and 8 bytes on 64 bit, so an LRESULT won't fit into a long (which is 4 bytes) if you compile for 64 bit.
Using WPARAM and LPARAM as parameter types is also important, as their size changes depending on the platform, too. See the answers to this question for more info: What are the definitions for LPARAM and WPARAM?
WPARAM is defined as unsigned __int64, LRESULT and LPARAM are __int64 in 64-bit Windows.
You have to change the signature of BrnDefDlgClass accordingly. If the WinAPI-provided typedefs were used instead of built-in types, it would be compilable on both 32 and 64-bit platforms.

Resources