LinuxQuestions.org

LinuxQuestions.org (/questions/)
-   Programming (https://www.linuxquestions.org/questions/programming-9/)
-   -   Why does my C program lookup libraries on runtime? (https://www.linuxquestions.org/questions/programming-9/why-does-my-c-program-lookup-libraries-on-runtime-289693/)

jarobman 02-13-2005 12:43 PM

Why does my C program lookup libraries on runtime?
 
I decided to create a neat little program out of boredom a few days ago. It works perfectly but whenever I run it, it produces weird output along with my own output. Every time a function call appears in my code, a line is sent to stdout that says that it is looking for the function in a file called libc.so.6 located in the directory /lib/tls. Here are two examples of what happens when I try to run my program:

Example 1: (my normal output is highlighted in dark red)

jarobman@linux:~/Documents> ./imessage samurai.jpg Hello World!
10603: symbol=strlen; lookup in file=./imessage
10603: symbol=strlen; lookup in file=/lib/tls/libc.so.6
10603: symbol=fgetc; lookup in file=./imessage
10603: symbol=fgetc; lookup in file=/lib/tls/libc.so.6
10603: symbol=printf; lookup in file=./imessage
10603: symbol=printf; lookup in file=/lib/tls/libc.so.6

ffd8
10603: symbol=fputc; lookup in file=./imessage
10603: symbol=fputc; lookup in file=/lib/tls/libc.so.6
10603: symbol=fclose; lookup in file=./imessage
10603: symbol=fclose; lookup in file=/lib/tls/libc.so.6
10603: symbol=free; lookup in file=./imessage
10603: symbol=free; lookup in file=/lib/tls/libc.so.6
10603: symbol=strlen; lookup in file=./imessage
10603: symbol=strlen; lookup in file=/lib/tls/libc.so.6

Filename: samurai.jpg
Message: Hello World! @


Example 2:

jarobman@linux:~/Documents> ./imessage samurai.jpg This is a message, fool!
11060: binding file ./imessage to /lib/tls/libc.so.6: normal symbol `strlen' [GLIBC_2.0]
11060: binding file ./imessage to /lib/tls/libc.so.6: normal symbol `fgetc' [GLIBC_2.0]
11060: binding file ./imessage to /lib/tls/libc.so.6: normal symbol `printf' [GLIBC_2.0]

ffd8
11060: binding file ./imessage to /lib/tls/libc.so.6: normal symbol `fputc' [GLIBC_2.0]
11060: binding file ./imessage to /lib/tls/libc.so.6: normal symbol `fclose' [GLIBC_2.1]
11060: binding file /lib/tls/libc.so.6 to /lib/tls/libc.so.6: normal symbol `free' [GLIBC_2.0]
11060: binding file /lib/tls/libc.so.6 to /lib/tls/libc.so.6: normal symbol `strlen' [GLIBC_2.0]

Filename: samurai.jpg
Message: This is a message, fool! @


Here is my code just in case: (This is a console program that accepts a JPEG file and either writes a message in in it [parameters after the file name] or retrieves an already placed message [no parameters after the file name])

Code:

#include <stdlib.h>
#include <stdio.h>
#include <string.h>

#define SOI 0xffd8 //image header
#define EOI 0xffd9 //end of image marker
#define HEADER_SIZE 128 //number of bytes in jpeg header
#define MASK 0x6a //byte mask for encoding

int main(int argc, char *argv[])
{
        char *usage = "Usage: imessage jpeg_file [message]";
        char *msg;
        int i, in, out, len;
        unsigned short int chksoi;
        FILE *input;
        if (argc >= 3)
        {
                if ((input = fopen(argv[1], "r+")) != NULL)
                {
                        for (i = 2; i < argc; i++)
                        {
                                msg = strcat(msg, argv[i]);
                                msg = strcat(msg, " ");
                        }
                        msg = strcat(msg, "@");
                        len = strlen(msg);
                        in = fgetc(input);
                        chksoi = in<<8;
                        in = fgetc(input);
                        chksoi |= in;
                        //
                        printf("%x\n", chksoi);
                        //
                        if (chksoi == SOI)
                        {
                                for(i = 2; i < HEADER_SIZE; i++)
                                {
                                        in = fgetc(input);
                                }
                                for (i = 0; i < len; i++)
                                {
                                        in = (msg[i] != '@') ? (int)msg[i]^MASK : (int)msg[i];
                                        out = fputc(in ,input);
                                }
                        }
                        else
                        {
                                printf("Error: Invalid JPEG image\n");
                        }
                        fclose(input);
                        printf("%s: %s\n", "Filename", argv[1]);
                        printf("%s: %s\n", "Message", msg);
                }
                else
                {
                        printf("%s %s %s\n", "Error: file", argv[1], "not found");
                }
        }
        else if (argc == 2)
        {
                if ((input = fopen(argv[1], "r")) != NULL)
                {
                        in = fgetc(input);
                        chksoi = in<<8;
                        in = fgetc(input);
                        chksoi |= in;
                        //
                        printf("%x\n", chksoi);
                        //
                        if (chksoi == SOI)
                        {
                                for (i = 2; i < HEADER_SIZE; i++)
                                {
                                        in = fgetc(input);
                                }
                                printf("Message Received: ");
                                while ((in = fgetc(input)) != '@')
                                {
                                        putchar(in^MASK);
                                }
                                printf("\n");
                        }
                        else
                        {
                                printf("Error: Invalid JPEG image\n");
                        }
                        fclose(input);
                }
                else
                {
                        printf("%s %s %s\n", "Error: file", argv[1], "not found");
                }
        }
        else
        {
                printf("%s\n", usage);
        }
        return 0;
}


Although my program works, I still could do without the ugly output. I have compiled my program with gcc version 3.3.3-41. I have no idea what the libc.so.6 file is and I don't know why it has to be searched through every time I call a C function. The main problem I have with this issue other that aesthetics is that this can cause a problem if I want to script my output to a file. Any solutions would be greatly appreciated. If I somehow, by a fluke, solve the problem myself, I will post the solution here for anyone having a similar problem.

jailbait 02-13-2005 02:08 PM

"Every time a function call appears in my code, a line is sent to stdout that says that it is looking for the function in a file called libc.so.6 located in the directory /lib/tls."

"I have no idea what the libc.so.6 file is and I don't know why it has to be searched through every time I call a C function."

Every time you call a C function your program will go through libc.so.6. What is peculiar is that your program is logging calls to libc.so.6. Check the gcc command you used to compile this program to see if you have specified any debug options.

http://gcc.gnu.org/onlinedocs/gcc/De...ugging-Options

----------------------------
Steve Stites

jarobman 02-13-2005 02:17 PM

I have only used the following commands to compile my program:
gcc imessage.c -Wall -o imessage

-and-

gcc imessage.c -o imessage

It is a mystery to me why my program is logging calls to libc.so.6 because when it comes to compiling C programs, the above is as simple as it gets.

crabboy 02-13-2005 02:18 PM

Does the file /lib/tls/libc.so.6 exist?

libc.so contains the all the basic c libraries that you compile into your code. Your program is using fgetc, strlen, printf and others. You can see the libraries that you program depends on by running:
Code:

ldd imessages
You will see /lib/tls/libc.so.6

Type the command:
Code:

locate libc.so.6
If that file does not exist, it may be picking up an older version of libc.so.6, but I'm not sure how. Look in your YaST configuration and see if all your programs and libraries are in good standing and you are not missing any depenedent pacakges.

jarobman 02-13-2005 02:33 PM

I just ran my program without typing in any parameters. The result is a call to printf with a string describing the usage of the program as a parameter. This call to printf does not cause a call to libc.so.6 to be logged! I noticed that this is the only case where my FILE struct is not assigned to a stream, so I'm tempted to think that that might be related to my overall problem. I will look into this issue some more for now...

jarobman 02-13-2005 02:36 PM

Quote:

Does the file /lib/tls/libc.so.6 exist?
Yes, the file does exist in my system in that exact location.

jarobman 02-13-2005 03:26 PM

I don't think my FILE stream has anything to do with my problem. I created the following program and it doesn't log calls to libc.so.6 at all:

Code:

#include <stdio.h>

int main(int argc, char *argv[])
{
        FILE *input;
        int i;
       
        input = fopen("samurai.jpg", "r+");
        for (i = 1; i < argc; i++)
        {
                printf("%s %c ", argv[i], fgetc(input));
        }
        fclose(input);
        printf("\n");
        return 0;
}

I do think that the problem might lie in my code; precisely in this section:
Code:

        if (argc >= 3)
        {
                if ((input = fopen(argv[1], "r+")) != NULL)
                {
                        for (i = 2; i < argc; i++)
                        {
                                msg = strcat(msg, argv[i]);
                                msg = strcat(msg, " ");
                        }
                        msg = strcat(msg, "@");
                        len = strlen(msg);
                        in = fgetc(input);
                        chksoi = in<<8;
                        in = fgetc(input);
                        chksoi |= in;
                        //
                        printf("%x\n", chksoi);
                        //
                        if (chksoi == SOI)
                        {
                                for(i = 2; i < HEADER_SIZE; i++)
                                {
                                        in = fgetc(input);
                                }
                                for (i = 0; i < len; i++)
                                {
                                        in = (msg[i] != '@') ? (int)msg[i]^MASK : (int)msg[i];
                                        out = fputc(in ,input);
                                }
                        }
                        else
                        {
                                printf("Error: Invalid JPEG image\n");
                        }
                        fclose(input);
                        printf("%s: %s\n", "Filename", argv[1]);
                        printf("%s: %s\n", "Message", msg);
                }
                else
                {
                        printf("%s %s %s\n", "Error: file", argv[1], "not found");
                }
        }

The lines in red are the ones that are responsible for making calls to libc.so.6. The weird thing about the output I decribed above is that it makes a call to libc.so.6 for the function free and an additional strlen function, both which are non-existant in my program (I only have one strlen function, but once a call to libc.so.6 is made, additional calls to the same function do not and should not result in additional calls to the library file). My theory is that my problem begins with the strlen function.

paulsm4 02-13-2005 04:02 PM

You're somehow invoking LD_DEBUG.

Look here:

http://www.wlug.org.nz/LD_DEBUG

Try this:
set|grep LD
<= IF YOU'VE SOMEHOW SET "LD_DEBUG" IN YOUR ENVIRONMENT, PLEASE
TRY *UNSETTING* IT AND RE-RUN YOUR PROGRAM

'Hope that helps .. PSM

jarobman 02-13-2005 06:01 PM

I ran set|grep LD but that didn't change my situation. I am not sure how to change anything in my environment variables. The link you provided didn't tell me much about how to solve my problem. However, I now have a focus point towards the grand solution of my problem. Thanks.

Tinkster 02-13-2005 06:41 PM

set | grep LD
wouldn't change the situation .... it would show you whether
LD_DEBUG is set or not ... that aside, do you compile the
program from a Makefile, and if so, did you "borrow" from
some other source, by any chance? Maybe the directive
is being invoked somewhere you haven't looked yet...



Cheers,
Tink

jarobman 02-14-2005 03:42 PM

I didn't compile from a makefile and I didn't borrow from another source. I made this program completely from scratch and as you can see from my code, I have only included three C standard libraries. I did similar operations in the test program that I wrote and the output was normal. I don't see anything unusual about my code that would cause this whole issue :confused: . It just doesn't make sense. If anyone can tell me how to change the LD_DEBUG_OUTPUT environment variable, please do. Thanks!

deiussum 02-14-2005 04:13 PM

Not sure if this is the cause of your problem, but it is definitely a problem:

Code:

        char *msg;
        int i, in, out, len;
        unsigned short int chksoi;
        FILE *input;
        if (argc >= 3)
        {
                if ((input = fopen(argv[1], "r+")) != NULL)
                {
                        for (i = 2; i < argc; i++)
                        {
                                msg = strcat(msg, argv[i]);
                                msg = strcat(msg, " ");
                        }
                        msg = strcat(msg, "@");

Maybe I'm missing it, but I see nowhere that you are allocating memory for msg. Usually you will get a segfault from code like this, but perhaps it is overwriting some other memory space and inadvertently turning on the debug messages?

jarobman 02-14-2005 04:41 PM

I don't think mallocs are required in this situation. What the string functions do is put data in some place in memory and I'm just assigning the pointer msg to that address. I haven't seen a single segmentation fault during the creation of my program so far.

aluser 02-14-2005 05:10 PM

Quote:

DESCRIPTION
The strcat() function appends the src string to the dest string over-
writing the `\0' character at the end of dest, and then adds a termi-
nating `\0' character. The strings may not overlap, and the dest
string must have enough space for the result.
Quote:

RETURN VALUE
The strcat() and strncat() functions return a pointer to the resulting
string dest.
It's a common mistake. In general, libc functions don't do allocation for you because they don't know how you want to handle a failure.

deiussum 02-15-2005 08:20 AM

Quote:

Originally posted by jarobman
What the string functions do is put data in some place in memory and I'm just assigning the pointer msg to that address.
Never assume anything about where memory is coming from. Whenever you have to use the phrase "some place in memory," you likely will have to allocate that memory yourself unless the documentation for the function explicitly states that it will allocate the memory. :)

As already stated, strcat just appends to the end of the pointer you give it, then returns that same pointer as a convenience. It does no memory allocation of its own.


All times are GMT -5. The time now is 08:22 PM.