Some help with a Makefile (gperftools)

I am drafting a Makefile for gperftools but am running into a few problems.

  1. I cannot get the syntax right to download the source tarball
  2. The compilation fails and I am unsure why (I do not see the build system pulling in my depends)

Grateful for any assistance.

Location of Makefile
Build failure log after manually placing tarball in to ./dl due to #1 above

Did you build from the Reposity? If so try to use the tar as source as suggested in the Ubuntu build instructions but probably you are just missing a build package https://github.com/gperftools/gperftools/releases/download/gperftools-2.10/gperftools-2.10.tar.gz

Yes, that is the source tarball I am using. Gives errors at least it does the way I wrote the Makefile. See above.

Probably these 3 errors are the problem

src/malloc_hook_mmap_linux.h:63:39: error: 'off64_t' has not been declared
   63 |                               int fd, off64_t offset) __THROW {
      |                                       ^~~~~~~
src/malloc_hook_mmap_linux.h:152:24: error: 'off64_t' has not been declared
  152 |                int fd, off64_t offset  ) __THROW
      |                        ^~~~~~~
src/malloc_hook_mmap_linux.h:167:33: error: 'off64_t' has not been declared
  167 |                         int fd, off64_t offset) __THROW {

Interesting that it was changed because of musl https://github.com/gperftools/gperftools/pull/765 Were there perhaps changes to musl that made the fix no longer necessary?

No idea :smiley:

Just try to change the variables specified in the error log back in the end it works.

Can you share a patch implementing the changes you’re proposing?

I don't know I'm not a programmer so I would have to look at the malloc_hook_mmap_linux.h probably only off64_t has to be changed to __off64_t but maybe something completely different has to be done.

I have changed the variables in the malloc_hook_mmap_linux.h now the code in the file should be replaced and tested if it works maybe I will try it later.

// -*- Mode: C++; c-basic-offset: 2; indent-tabs-mode: nil -*-
// Copyright (c) 2005, Google Inc.
// All rights reserved.
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are
// met:
//
//     * Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
//     * Redistributions in binary form must reproduce the above
// copyright notice, this list of conditions and the following disclaimer
// in the documentation and/or other materials provided with the
// distribution.
//     * Neither the name of Google Inc. nor the names of its
// contributors may be used to endorse or promote products derived from
// this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

// ---
// Author: Sanjay Ghemawat <opensource@google.com>

// We define mmap() and mmap64(), which somewhat reimplements libc's mmap
// syscall stubs.  Unfortunately libc only exports the stubs via weak symbols
// (which we're overriding with our mmap64() and mmap() wrappers) so we can't
// just call through to them.

#ifndef __linux
# error Should only be including malloc_hook_mmap_linux.h on linux systems.
#endif

#include <errno.h>
#include <sys/mman.h>
#include <sys/syscall.h>
#include <unistd.h>

// The x86-32 case and the x86-64 case differ:
// 32b has a mmap2() syscall, 64b does not.
// 64b and 32b have different calling conventions for mmap().

// I test for 64-bit first so I don't have to do things like
// '#if (defined(__mips__) && !defined(__MIPS64__))' as a mips32 check.
#if defined(__x86_64__) \
    || defined(__PPC64__) \
    || defined(__aarch64__) \
    || defined(__loongarch64) \
    || (defined(_MIPS_SIM) && (_MIPS_SIM == _ABI64 || _MIPS_SIM == _ABIN32)) \
    || defined(__s390__) || (defined(__riscv) && __riscv_xlen == 64)

static inline void* do_mmap64(void *start, size_t length,
                              int prot, int flags,
                              int fd, __off64_t offset) __THROW {
#if defined(__s390__)
  long args[6] = { (long)start, (long)length, (long)prot, (long)flags,
                   (long)fd, (long)offset };
  return (void*)syscall(SYS_mmap, args);
#else
  return (void*)syscall(SYS_mmap, start, length, prot, flags, fd, offset);
#endif
}

#define MALLOC_HOOK_HAVE_DO_MMAP64 1

#elif defined(__i386__) || defined(__PPC__) || defined(__mips__) || \
      defined(__arm__)

static inline void* do_mmap64(void *start, size_t length,
                              int prot, int flags,
                              int fd, __off64_t offset) __THROW {
  void *result;

  // Try mmap2() unless it's not supported
  static bool have_mmap2 = true;
  if (have_mmap2) {
    static int pagesize = 0;
    if (!pagesize) pagesize = getpagesize();

    // Check that the offset is page aligned
    if (offset & (pagesize - 1)) {
      result = MAP_FAILED;
      errno = EINVAL;
      goto out;
    }

    result = (void *)syscall(SYS_mmap2,
                             start, length, prot, flags, fd,
                             (off_t) (offset / pagesize));
    if (result != MAP_FAILED || errno != ENOSYS)  goto out;

    // We don't have mmap2() after all - don't bother trying it in future
    have_mmap2 = false;
  }

  if (((off_t)offset) != offset) {
    // If we're trying to map a 64-bit offset, fail now since we don't
    // have 64-bit mmap() support.
    result = MAP_FAILED;
    errno = EINVAL;
    goto out;
  }

#ifdef __NR_mmap
  {
    // Fall back to old 32-bit offset mmap() call
    // Old syscall interface cannot handle six args, so pass in an array
    int32 args[6] = { (int32) start, (int32) length, prot, flags, fd,
                      (int32)(off_t) offset };
    result = (void *)syscall(SYS_mmap, args);
  }
#else
  // Some Linux ports like ARM EABI Linux has no mmap, just mmap2.
  result = MAP_FAILED;
#endif

 out:
  return result;
}

#define MALLOC_HOOK_HAVE_DO_MMAP64 1

#endif  // #if defined(__x86_64__)


#ifdef MALLOC_HOOK_HAVE_DO_MMAP64

// We use do_mmap64 abstraction to put MallocHook::InvokeMmapHook
// calls right into mmap and mmap64, so that the stack frames in the caller's
// stack are at the same offsets for all the calls of memory allocating
// functions.

// Put all callers of MallocHook::Invoke* in this module into
// malloc_hook section,
// so that MallocHook::GetCallerStackTrace can function accurately:

// Make sure mmap64 and mmap doesn't get #define'd away by <sys/mman.h>
# undef mmap64
# undef mmap

extern "C" {
  void* mmap64(void *start, size_t length, int prot, int flags,
               int fd, __off64_t offset  ) __THROW
    ATTRIBUTE_SECTION(malloc_hook);
  void* mmap(void *start, size_t length,int prot, int flags,
             int fd, off_t offset) __THROW
    ATTRIBUTE_SECTION(malloc_hook);
  int munmap(void* start, size_t length) __THROW
    ATTRIBUTE_SECTION(malloc_hook);
  void* mremap(void* old_addr, size_t old_size, size_t new_size,
               int flags, ...) __THROW
    ATTRIBUTE_SECTION(malloc_hook);
  void* sbrk(intptr_t increment) __THROW
    ATTRIBUTE_SECTION(malloc_hook);
}

extern "C" void* mmap64(void *start, size_t length, int prot, int flags,
                        int fd, __off64_t offset) __THROW {
  MallocHook::InvokePreMmapHook(start, length, prot, flags, fd, offset);
  void *result;
  if (!MallocHook::InvokeMmapReplacement(
          start, length, prot, flags, fd, offset, &result)) {
    result = do_mmap64(start, length, prot, flags, fd, offset);
  }
  MallocHook::InvokeMmapHook(result, start, length, prot, flags, fd, offset);
  return result;
}

# if !defined(__USE_FILE_OFFSET64) || !defined(__REDIRECT_NTH)

extern "C" void* mmap(void *start, size_t length, int prot, int flags,
                      int fd, off_t offset) __THROW {
  MallocHook::InvokePreMmapHook(start, length, prot, flags, fd, offset);
  void *result;
  if (!MallocHook::InvokeMmapReplacement(
          start, length, prot, flags, fd, offset, &result)) {
    result = do_mmap64(start, length, prot, flags, fd,
                       static_cast<size_t>(offset)); // avoid sign extension
  }
  MallocHook::InvokeMmapHook(result, start, length, prot, flags, fd, offset);
  return result;
}

# endif  // !defined(__USE_FILE_OFFSET64) || !defined(__REDIRECT_NTH)

extern "C" int munmap(void* start, size_t length) __THROW {
  MallocHook::InvokeMunmapHook(start, length);
  int result;
  if (!MallocHook::InvokeMunmapReplacement(start, length, &result)) {
    result = syscall(SYS_munmap, start, length);
  }
  return result;
}

extern "C" void* mremap(void* old_addr, size_t old_size, size_t new_size,
                        int flags, ...) __THROW {
  va_list ap;
  va_start(ap, flags);
  void *new_address = va_arg(ap, void *);
  va_end(ap);
  void* result = (void*)syscall(SYS_mremap, old_addr, old_size, new_size, flags,
                                new_address);
  MallocHook::InvokeMremapHook(result, old_addr, old_size, new_size, flags,
                               new_address);
  return result;
}

#ifdef HAVE___SBRK
// libc's version:
extern "C" void* __sbrk(intptr_t increment);

extern "C" void* sbrk(intptr_t increment) __THROW {
  MallocHook::InvokePreSbrkHook(increment);
  void *result = __sbrk(increment);
  MallocHook::InvokeSbrkHook(result, increment);
  return result;
}

#endif

/*static*/void* MallocHook::UnhookedMMap(void *start, size_t length, int prot,
                                         int flags, int fd, off_t offset) {
  void* result;
  if (!MallocHook::InvokeMmapReplacement(
          start, length, prot, flags, fd, offset, &result)) {
    result = do_mmap64(start, length, prot, flags, fd, offset);
  }
  return result;
}

/*static*/int MallocHook::UnhookedMUnmap(void *start, size_t length) {
  int result;
  if (!MallocHook::InvokeMunmapReplacement(start, length, &result)) {
    result = syscall(SYS_munmap, start, length);
  }
  return result;
}

#undef MALLOC_HOOK_HAVE_DO_MMAP64

#endif  // #ifdef MALLOC_HOOK_HAVE_DO_MMAP64

I patched with your file but the build still fails.

That would have been too easy. We can only hope that the developers can say something about the error. Wait I found something https://stackoverflow.com/questions/22663897/unknown-type-name-off64-t

Redefine off64_t to __off64_t in your compile flag. Edit your Makefile so it contains:

CFLAGS= -Doff64_t=__off64_t
then, just run $ make 1 (assuming you have 1.c in your directory)

I added the following to the Makefile but it still errored out:

TARGET_CFLAGS += -Doff64_t=__off64_t
...
OpenWrt-libtool: compile:  x86_64-openwrt-linux-musl-g++ -DHAVE_CONFIG_H -I. -I./src -I./src -I/scratch/union/staging_dir/toolchain-x86_64_gcc-12.3.0_musl/usr/include -I/scratch/union/staging_dir/toolchain-x86_64_gcc-12.3.0_musl/include/fortify -I/scratch/union/staging_dir/toolchain-x86_64_gcc-12.3.0_musl/include -DNO_TCMALLOC_SAMPLES -DNO_HEAP_CHECK -DNDEBUG -Wall -Wwrite-strings -Woverloaded-virtual -Wno-sign-compare -fno-omit-frame-pointer -momit-leaf-frame-pointer -Wno-unused-result -fsized-deallocation -faligned-new -fno-omit-frame-pointer -DFORCED_FRAME_POINTERS -Os -pipe -fno-caller-saves -fno-plt -fhonour-copts -fmacro-prefix-map=/scratch/union/build_dir/target-x86_64_musl/gperftools-2023-07-13-4a923a6b=gperftools-2023-07-13-4a923a6b -Wformat -Werror=format-security -fstack-protector -D_FORTIFY_SOURCE=1 -Wl,-z,now -Wl,-z,relro -Doff64_t=__off64_t -Doff64_t=__off64_t -c src/internal_logging.cc -o src/libtcmalloc_minimal_internal_la-internal_logging.o >/dev/null 2>&1
<command-line>: error: '__off64_t' has not been declared
src/malloc_hook_mmap_linux.h:63:39: note: in expansion of macro 'off64_t'
   63 |                               int fd, off64_t offset) __THROW {
      |                                       ^~~~~~~
<command-line>: error: '__off64_t' has not been declared
src/malloc_hook_mmap_linux.h:152:24: note: in expansion of macro 'off64_t'
  152 |                int fd, off64_t offset  ) __THROW
      |                        ^~~~~~~
<command-line>: error: '__off64_t' has not been declared
src/malloc_hook_mmap_linux.h:167:33: note: in expansion of macro 'off64_t'
  167 |                         int fd, off64_t offset) __THROW {
      |                                 ^~~~~~~

@xxxx - I got it, see: Makefile

Nice to hear if you want to provide the ipk files of Snort and gperftools I will test it.

Sounds good upstream claims to have fixed the build issue. I will try it later today and provide packages if successful.

What dimensions are supposed to be improved by goerftools?

I can not say I have only tested it on Linux Mate according to the instructions I posted in the other thread and have configured there snort as Ips in nfq mode. Have simpler half my configs from the router taken and adapted. What I saw was that the memory consumption was slightly higher but the Cpu load was quite low at a throughput of almost 200Mbit (smb copy) only a maximum of 6% on a Ryzen 4800h at a test download the load of the browser was even higher than that of Snort.

  1. OK so I got gperftools to build but it required patching it with with this which I do not believe is right. The package itself needs to be split into a runtime and headers but for now it does build and I can build snort3 against it. Link to upstream ticket which is currently closed but waiting to hear back as to why the build fails.

  2. I modified snort3 to build with both hyperscan and with gperftools. See here.

  3. I have snort3 up and running with this support and it seems just fine.

You can download these files which I realized just now that build against master not openwrt-23.05-rc2 like you asked for before. Will they work for you? Link.

...
Feature options:
    DAQ Modules:    Dynamic
    libatomic:      User-specified
    Hyperscan:      ON
    ICONV:          ON
    Libunwind:      OFF
    LZMA:           OFF
    RPC DB:         TIRPC
    SafeC:          OFF
    TCMalloc:       ON
    JEMalloc:       OFF
    UUID:           ON
    NUMA:           OFF
...

Am I supposed to see something about TCMalloc support in the snort --version?

# snort --version

   ,,_     -*> Snort++ <*-
  o"  )~   Version 3.1.65.0
   ''''    By Martin Roesch & The Snort Team
           http://snort.org/contact#team
           Copyright (C) 2014-2023 Cisco and/or its affiliates. All rights reserved.
           Copyright (C) 1998-2013 Sourcefire, Inc., et al.
           Using DAQ version 3.0.12
           Using LuaJIT version 2.1.0-beta3
           Using OpenSSL 3.0.9 30 May 2023
           Using libpcap version 1.10.4 (with TPACKET_V3)
           Using PCRE version 8.45 2021-06-15
           Using ZLIB version 1.2.13
           Using Hyperscan version 5.4.2 2023-07-12

I am bit concerned that I did not build either gperftools or snort3 against it correctly because if I remove the gperftools package from the box, snort3 continues to run. Seems like it would fail due to missing libs...

So I get this when I complie snort3:

-- Configuring done (1.0s)
CMake Warning at src/CMakeLists.txt:212 (target_link_libraries):
  Target "snort" requests linking to directory
  "/scratch/union/staging_dir/target-x86_64_musl/usr/lib".  Targets may link
  only to libraries.  CMake is dropping the item.

Thinking that is the problem...?