无法从共享对象打印到文件

时间:2018-07-13 22:01:57

标签: c linux shared-libraries systems-programming ltrace

我之前在这里看到过与此问题类似的问题,但是我无法从这些问题的答案中解决我的问题。

我有一个文件libfoo.c,我将从该文件创建共享对象。使用gcc的__attribute__((constructor)),我想在加载此共享库时将消息打印到文件中:

#include <stddef.h>
#include <stdio.h>
#include <string.h>
#include <unistd.h>

static char *term = NULL;

static void init (void) __attribute__((constructor));

static void
init (void)
{
  FILE *f = fopen ("lib.log", "w");

  if (f)
    {
      if (isatty (STDOUT_FILENO))
        {
          char *tmp = ttyname (STDERR_FILENO);
          if (tmp && *tmp)
            {
              term = strdup (tmp); // nevermind the memory leak
              fprintf (f, "Found terminal %s\n", term);
            }
        }
      else
        fprintf (f, "Failed to find terminal\n");

      fclose(f);
   }
}

void *
malloc (size_t size)
{
  return NULL;
}

伪malloc实现(将在以后扩展)应在另一个伪程序中替换stdlib.h的malloc,该伪程序的源代码位于main.c中:

#include <stdlib.h>

int main (void)
{
  char *m = malloc(1024);
  (void)m;
  return 0;
}

我正在如下编译和链接两个文件:

gcc -o main main.c
gcc -fpic -shared -o libfoo libfoo.c

然后当我执行以下命令时,将不会创建任何文件,也不会记录任何输出:

LD_PRELOAD=$(readlink -f libfoo) ./main

这是怎么回事?附带说明:如何使用ltrace调试此类问题? ltrace "LD_PRELOAD=... ./main"是无效命令。

编辑:这是怎么回事?似乎至少printf在共享库中有效,但是如果我在printf内调用malloc在程序段中运行,则仅在设置函数中有效。为了至少找出stdout所连接的终端,我做了以下操作(在设置功能内):

// ...

char buf[100];
buf[readlink ("/proc/self/fd/1", buf, 100)] = '\0';
printf ("STDOUT (buf): %s\n", buf);

char *tmp = ttyname (1);
printf ("STDOUT (ttyname): %s, %s\n", tmp, strerror (errno));

// ...

此打印:

STDOUT (buf): /dev/pts/1
STDOUT (ttyname): (null), Success

根据ttyname联机帮助页,第二行输出应该是不可能的。我在这里完全误解了吗?

1 个答案:

答案 0 :(得分:0)

这是我根据您的代码创建的运行文件,它运行完美,生成了一个文件:lib.log

文件内容:lib.log

Found terminal /dev/pts/1

现在,我运行的代码是

#include <stddef.h>
#include <stdio.h>
#include <string.h>
#include <unistd.h>

static char *term = NULL;

static void init (void) __attribute__((constructor));

static void init (void)
{
    FILE *f = fopen ("lib.log", "w");

    if (f)
    {
        if (isatty (STDOUT_FILENO))
        {
            char *tmp = ttyname (STDERR_FILENO);
            if (tmp && *tmp)
            {
                term = strdup (tmp); // nevermind the memory leak
                fprintf (f, "Found terminal %s\n", temp);
            }
        }

        else
            fprintf (f, "Failed to find terminal\n");

      fclose(f);
   }

   else
   {
       perror( "fopen failed" );
   }
}


void *
myMalloc (size_t size)
{
    (void)size;
    return NULL;
}


int main (void)
{
    char *m = myMalloc(1024);
    (void)m;
    return 0;
}

当然,您发布的代码缺少头文件。您的main.c文件和libfoo.c文件应引用/包含这样的头文件