Compile a static binary which code there a function gethostbyname - c++

How to resolve compile a static binary which code include a function gethostbyname and if compiled without warning like this:
warning: Using 'gethostbyname' in statically linked applications
requires at runtime the shared libraries from the glibc version used
for linking
I compile on ubuntu 12.04 with command:
$ gcc -static lookup.c -o lookup
This is code for lookup.c:
/* lookup.c */
#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <string.h>
#include <errno.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <netdb.h>
extern int h_errno;
int main(int argc,char **argv) {
int x, x2;
struct hostent *hp;
for ( x=1; x<argc; ++x ) {
hp = gethostbyname(argv[x]);
if ( !hp ) {
fprintf(stderr,
"%s: host '%s'\n",
hstrerror(h_errno),
argv[x]);
continue;
}
printf("Host %s : \n" ,argv[x]);
printf(" Officially:\t%s\n", hp->h_name);
fputs(" Aliases:\t",stdout);
for ( x2=0; hp->h_aliases[x2]; ++x2 ) {
if ( x2 ) {
fputs(", ",stdout);
}
fputs(hp->h_aliases[x2],stdout);
}
fputc('\n',stdout);
printf(" Type:\t\t%s\n",
hp->h_addrtype == AF_INET
? "AF_INET" : "AF_INET6");
if ( hp->h_addrtype == AF_INET ) {
for ( x2=0; hp->h_addr_list[x2]; ++x2 ) {
printf(" Address:\t%s\n",
inet_ntoa( *(struct in_addr *)
hp->h_addr_list[x2]));
}
}
putchar('\n');
}
return 0;
}
I want to if I check via $ file lookup will get output like this:
lookup: ELF 32-bit LSB executable, Intel 80386, version 1 (GNU/Linux),
statically linked, for GNU/Linux 2.6.24,
BuildID[sha1]=0x6fcb2684ad8e5e842036936abb50911cdde47c73, not stripped
Not like this:
lookup: ELF 32-bit LSB executable, Intel 80386, version 1 (SYSV),
dynamically linked (uses shared libs), for GNU/Linux 2.6.24,
BuildID[sha1]=0xf9f18671751927bea80de676d207664abfdcf5dc, not stripped
If you commented with suggested I must use without static because different libc every linux I knew it, I hope you do not need to comment.
Why do I persist in for static?
Because there I need to do to mandatory use static, binary files must be static and not dynamic.
I have more than 2 weeks looking for this but so far have not succeeded.
Thanks for help me to resolve my heavy problem.

What you are asking for is going to be very difficult.
See this StackOverflow question about getaddrinfo. Basically, underneath getaddrinfo/gethostbyname is glibc's NSS layer. This allows a sysadmin to say "use DNS for resolving hostnames to IP addresses", or "use LDAP", or "don't use anything other than /etc/hosts". This control is at runtime; the sysadmin can at any point change the way hostnames are resolved to IPs.
Because of this flexibility, all of the name-resolution calls in glibc use helper libraries (plugins, basically) to do the grunt work of resolution. There's one shared library for LDAP addressing, one for files, one for DNS, one for YP, and so on and so on.
If you want your program to be 100% statically linked, you're going to have to go elsewhere (NOT gethostbyname) to convert a hostname to an IP address. You could do this with a resolver library like uDNS (not this exact one - there are similar tools available), but you should keep in mind that your binary is not going to do the right thing on systems which are configured not to use DNS!
Instead, I would recommend just leaving the program (technically) dynamically linked. If you really want to make sure it will run on any platform, you could even ship glibc with the binary - although doing this would require LGPL conformance. Leaving this one dynamic link in place will only mean you won't work on systems with the wrong glibc version - not a huge compatibility issue.
Speaking of license compliance, it's worth noting that if you statically link glibc, you most likely have to ship the source code for your entire application to comply with glibc's LGPL license. I am not a lawyer, and this is not qualified legal advice, but reading the LGPL makes it very clear that applications statically linking glibc must be open-source. See this StackOverflow question on the topic.

I get the same warning and to fix it I recompiled glibc. Turn on switch --enable-static-nss when configuring to get it to work.

I have 2 answers -
Keep the main part of your program statically linked, and separate out a single function program to just call gethostbyname(). Allow the latter to be dynamically linked. Using fork then exec execute this separate program to get the address for a domain name. Instead of fork then exec you could use system() though it takes longer (a whole millisecond) that should not be of concern since you're searching nameservers on the internet anyway, which takes a time.
Write the source code to do the DNS, as I have done. Compile it into an archive (.a) and have it searched in the static linking.

use ip instead of using domain name, that work for me

Related

Reduce exported symbols of a third party library

I have code that works fine, but if I link my project to a third party lib libabc.so (source unavailable), then all of the sudden I get a segmentation fault.
I have a main that looks like this
#include <opencv2/imgcodecs.hpp>
#include "Abc.h"
int main(int argc, char **argv)
{
Abc dummyAbc;
auto img = cv::imread("dummy.png");
cv::imwrite("123.png", img);
return 0;
}
The CMakeList.txt is as follows
cmake_minimum_required(VERSION 3.1)
set(CMAKE_C_STANDARD 11)
find_package(OpenCV COMPONENTS core highgui imgcodecs)
include_directories(${OpenCV_INCLUDE_DIR})
add_executable(my_project Main.cpp)
target_link_libraries(my_project ${OpenCV_LIBRARIES} abc)
This compiles well, but segfault when running. If I remove the line
Abc dummyAbc;
then all works fine (i.e. there is no problem with missing file, or opencv).
If I inspect the stack of the segfault, I see that:
Thread 1 "my_project" received signal SIGSEGV, Segmentation fault.
0x00007fdea96836b3 in png_destroy_write_struct () from /usr/local/lib/libabc.so
where png_destroy_write_struct is being called by cv::imwrite.
Both libpng.so and libabc.so (!!) export png_destroy_write_struct it actually exports all of the libpng API (which I assume it was statically linked to?). I assume this is the problem? I do no want openCV to see whatever libabc.so exports... How can I do this?
I tried to use objcopy --prefix-symbols abc_ libabc.so but somehow it did not help, now the crash happens at abc_png_destroy_write_struct.
I assume this is the problem?
Yes: that is very likely: libabc.so has statically linked (probably different version of) libpng, and introduces symbol conflict.
I do no want openCV to see whatever libabc.so exports... How can I do this?
You can't. You must contact libabc.so developer, and tell them to hide libpng symbols.
The only other option (for single process execution) is to dynamically load libabc.so.
This can be done via dlopen("liabc.so.", RTLD_LOCAL), and even that may not work (depending on exactly how libabc.so was linked) -- it may cause libabc.so to bind to your version of libpng, and crash.
On Linux, you could also possibly use dlmopen(LM_ID_NEWLM, "libabc.so", ...) which will completely isolate libabc.so from the rest of your code, and may work if libabc.so was linked to include all of its dependencies (or you can bring them into the new loader namespace explicitly).
Finally, as Eljay commented here, you could use inter-process communication and have a completely separate process load libabc.so. This will have much worse performance than using libabc.so directly, but is better than nothing.
To add to EmployedRussian's answer about using dlmopen-based approach to isolate libabc.so from the rest of your code: to avoid messing with dlsym and function pointers in that case you could automatically generate wrappers for needed library functions via Implib.so:
$ cat mysymbols.txt
foo
bar
$ cat mycallback.c
#define _GNU_SOURCE
#include <dlfcn.h>
#include <stdio.h>
#include <stdlib.h>
#ifdef __cplusplus
extern "C"
#endif
// Dlopen callback that loads library to dedicated namespace
void *mycallback() {
void *h = dlmopen(LM_ID_NEWLM, "libabc.so", RTLD_LAZY | RTLD_DEEPBIND);
if (h)
return h;
fprintf(stderr, "dlmopen failed: %s\n", dlerror());
exit(1);
}
$ implib-gen.py --dlopen-callback=mycallback --symbol-list=mysymbols.txt libabc.so
$ ... # Link your app with libabc.tramp.S, libabc.init.c and mycallback.c
I would try strip. See this for details: https://linux.die.net/man/1/strip

C++ Library Cross-Calling

I'm not really sure if that is the actual name of what I mean, but you'll get it.
Supose I have 3 projects, 2 of them builds as libraries, and the other one as an executable. For my scenario I'll use MSVC++ and the libraries will be dynamic (DLLs), and of course executable .exe, but I also want to if static libraries are also included.
And please, if I'm wrong on any of my assumptions, please correct me.
In the first library project, FirstLib.h:
#pragma once
#include <SecondLib.h>
#ifdef DLLONE_BUILD
#define DLLONE_API __declspec(dllexport)
#else
#define DLLONE_API __declspec(dllimport)
#endif
int DLLONE_API MainOne();
int DLLONE_API InternalOne();
and FirstLib.cpp:
#include <FirstLib.h>
int MainOne() { return InternalTwo(); }
int InternalOne() { return 100; }
Similarly, in the first project, SecondLib.h:
#pragma once
#include <FirstLib.h>
#ifdef DLLTWO_BUILD
#define DLLTWO_API __declspec(dllexport)
#else
#define DLLTWO_API __declspec(dllimport)
#endif
int DLLTWO_API MainTwo();
int DLLTWO_API InternalTwo();
SecondLib.cpp:
#include <SecondLib.h>
int MainTwo() { return InternalOne(); }
int InternalTwo() { return 200; }
Finally, in the executable project, main.cpp:
#include <FirstLib.h>
#include <SecondLib.h>
int main() { return MainOne() + MainTwo(); }
So when compiling the two libraries, I obtain the two .dll files, and two .lib files. Each library must have the other library .lib to link.
Then, the executable must be linked with the two .lib, and when executed, .dll should be in a known path for the exe, be the same path or some PATH.
Now for the questions:
Is doing this a correct aproach, or should be avoided?
Exe needs the two dlls, but each dll needs the other dll. Does each dll loads the other one again, or uses the same loaded version from .exe?
If they were static libraries, would each library be loaded two times, or just one? Or none of them?
And if you have a good resource where I can find more about this, it will be really apreciated.
Thanks in advance!
UPDATE as why would I do this : Imagine creating an engine.
I have (just to be consistent with the previous scenario) a library called Kernel, and a library called System. Also a binary project.
Kernel has the code regarding program execution (main loop), handling, base clases and other high level things.
System has the code regarding HAL and low level code. OpenGL things, file IO things, etc.
Binary has the main function, and program specific implementation of the engine.
Why do I need that cross-linking:
Kernel in Binary: main() (Binary) calls Kernel.Initialize() (Kernel).
System in Binary: CreateActor()(Binary) calls System.OpenGl.MeshCreate() (System)
System in Kernel: Kernel.Initialize()(Kernel) Initializes the Kernel, but also the System by calling System.Initialize()(System).
Kernel in System: class System(System) inherits from class Object(Kernel)
I know i could avoid this circular dependency by, say, Initializing System from binary calling System.Initialize()after Kernel.Initialize().
But then, Kernel will depend on no one, System would depend on Kernel, and Binary on both Kernel and System.
So my question remains in this case too
Is removing the cross dependency but to have this scheme a better aproach?
Same as question two: Does Binary and System both depending on Kernel as well asBinary in System represents double code, double loading or a performance or size downgrade or some kind of undesirable effect?

The procedure entry point __gxx_personality_v0 could not be located in the dynamic link library libstdc++-6.dll

I got that error when trying to run my opencv application. I´m using Windows7,CodeBlocks 12.11, opencv2.4.4 and MinGW compiler (the one that comes in CodeBlocks). It compiles and creates the executable but when i try to run it crashes with the procedure entry point error.
I have added C:\programs\CodeBlocks\Mingw\bin to "PATH" variable and i know there is libstdc++-6.dll.
I don´t know what´s hapenning.
This is the simple code:
include <iostream>
include <opencv2/highgui/highgui.hpp>
using namespace std;
using namespace cv;
int main()
{
cout << "Hello world!" << endl;
namedWindow("window");
Mat image=imread("mustang.jpg",CV_LOAD_IMAGE_COLOR);
imshow("window",image);
waitKey(0);
return 0;
}
The libstdc++-6.dll contains the runtime environment. It is an implementation of fundamental routines, such as the heap manager or the exception handling.
These fundamental routines are used in nearly every program. Thus, it would be a waste of memory to put a copy of them into every program. That is why they are usually packed into a shared library (DLL). The programs can then request the DLL when they need the routines of the runtime.
In your case, the libstdc++-6.dll contains a wrong version of the runtime. There are two possibilities:
Find a libstdc++-6.dll that contains the correct version of the runtime and copy it into the directory of your executable. You can determine whether a DLL is the correct one by running nm libstdc++-6.dll | grep personality. If the __gxx_personality_v0 shows up in the list, then you probably have the correct DLL.
Put a copy of the runtime environment into the executable. You can do this by adding -static-libgcc -static-libstdc++ to your linker parameters.
This question seems to have been answered several times here on stackoverflow.
What is __gxx_personality_v0 for? as one of them

How to link an archive without depending on an IDE?

I've been using a TCP sockets tutorial for C++, and came across the following line -
Before we begin, you will need to include winsock.h and link libws2_32.a to your project in order to use the API that are necessary for TCP/IP. If this is not possible, use LoadLibrary() to load ws2_32.dll at runtime, or some similar method.
After some research, I found a source that claimed this could be done with the following two lines -
#include <winsock.h>
#pragma comment(lib, "ws2_32.lib")
However, one of the two seem to not be working (I assume that it would be the second line, as the first is fairly straightforward). Here is the code I am trying to run -
#include <iostream>
#include <winsock.h>
#pragma comment(lib, "ws2_32.lib")
int main() {
std::cout << gethostbyname("www.google.com") << std::endl;
return 0;
}
This code, which should be printing the IP address of Google, instead gives the following error -
C:\Users\Owner\AppData\Local\Temp\ccOXoE0F.o:SC.cpp:(.text+0x1e): undefined reference to 'gethosebyname#4'
collect2: ld returned 1 exit status
Some more googling revealed that the reason for this is an improper linking of the library. According to these sources, the only way to link this is through an IDE. I generally use Notepad++ along with the command prompt, and so I ask if it is possible to properly link this archive without using an IDE.
If it isn't possible, then it looks like I'll have to get back into using IDEs.
No, IDEs have nothing to do with this, and your desire is correct and entirely understandable. Since you seem to be on Windows, I'm not sure what kind of command-line toolchain you are using, but if it's one of the GNU-compatible ones (GCC with MinGW, for example), then you can specify the -lws2_32 linker flag to link against the library.

Exe build by Code blocks is almost 57 times larger than the same code build by Visual studio

This code:
#include <iostream>
using namespace std;
int main()
{
cout << "Hello world!\n";
return 0;
}
when comiled give size 457KB in Code::Blocks with GCC 4.4.1 and only 8KB (eight) in VS2010. Both compilers optimized for size.
Anyone knows why such a difference?
This is due to the c++ standard library being linked statically by g++, whereas VS will link it dynamically. A quick check using gcc under cygwin gives me approximately same sizes, and the resulting exe only import some C functions.
#include <stdio.h>
int main() {
printf("Hello world\n");
return 0
}
On the other hand, this application compiled to the same minimal EXE under gcc, as it does not require any c++ functionality.
You are right, the executable by gcc is obviously larger, in your case 57 times larger than that built by vc++.
The main reason is the one made with
GCC won't require any external
dependencies to run while the one made
with VS2010 would need at least its runtime
files to be present on the system.
For instance, say you try it on some friend's computer with no vs2010 installed, rather try earlier OS like XP with no chance of having VS2010 runtimes even.
The one built with GCC will have no problems while the one made with VS2010 would throw an error of missing runtime file ( dependency ).
Hope this helped, if it didn't or you have any other question in your mind, feel free to ask and I'll be glad to help :)