unofficial mirror of emacs-devel@gnu.org 
 help / color / mirror / code / Atom feed
From: Elad Lahav <elahav@blackberry.com>
To: "emacs-devel@gnu.org" <emacs-devel@gnu.org>
Subject: Emacs on QNX
Date: Sun, 22 Oct 2017 22:13:55 +0000	[thread overview]
Message-ID: <1508710435.8718.6.camel@blackberry.com> (raw)

[-- Attachment #1: Type: text/plain, Size: 2968 bytes --]

Hello all,

I built Emacs on QNX 7.0. For the most part, the process was straight-
forward and required only minimal changes to the source (see below for
a diff). However, I ran into a problem when trying to run Emacs. The
investigation pointed to the use of sbrk(), which QNX dropped many
years ago. There is still a stub that returns -1 and sets errno to
ENOMEM, but the Emacs code doesn't check for that, and interprets the
result as the address 0xffffffffffffffff. Hilarity ensues.

To overcome the problem, I wrote a naive implementation of sbrk() in a
dynamically-linked library (attached). It doesn't fully adhere to the
original semantics of sbrk(), but is enough to get Emacs running
properly.

Why is sbrk() still used? With 64-bit address spaces and ASLR it is
hard to imagine this API being useful. I am surprised that other
operating systems still support it. Is there a different route I can
take that doesn't require the emulated sbrk()?

Thanks,
--Elad


diff -u -r emacs-25.2.orig/configure.ac emacs-25.2/configure.ac
--- emacs-25.2.orig/configure.ac	2017-02-03 09:34:30.000000000 -0500
+++ emacs-25.2/configure.ac	2017-10-22 03:01:12.000000000 -0400
@@ -698,6 +698,14 @@
     esac
   ;;
 
+  ## QNX Neutrino 
+  *-nto-qnx* )
+    echo Found QNX
+    opsys=qnxnto
+    CFLAGS="$CFLAGS -D__NO_EXT_QNX"
+    LDFLAGS="$LDFLAGS -L/usr/lib -lsocket -lsbrk"
+  ;;
+
   ## Intel 386 machines where we don't care about the manufacturer.
   i[3456]86-*-* )
     case "${canonical}" in
@@ -4465,7 +4473,7 @@
     AC_DEFINE(PTY_TTY_NAME_SPRINTF, [])
     ;;
 
-  gnu | openbsd )
+  gnu | openbsd | qnxnto )
     AC_DEFINE(FIRST_PTY_LETTER, ['p'])
     ;;
 
diff -u -r emacs-25.2.orig/src/unexelf.c emacs-25.2/src/unexelf.c
--- emacs-25.2.orig/src/unexelf.c	2017-02-03 05:25:45.000000000 -0500
+++ emacs-25.2/src/unexelf.c	2017-10-22 03:11:10.000000000 -0400
@@ -58,7 +58,9 @@
 #include <sys/types.h>
 #include <unistd.h>
 
-#if !defined (__NetBSD__) && !defined (__OpenBSD__)
+#if defined(__QNX__)
+#include <sys/elf.h>
+#elif !defined (__NetBSD__) && !defined (__OpenBSD__)
 #include <elf.h>
 #endif /* not __NetBSD__ and not __OpenBSD__ */
 #include <sys/mman.h>

---------------------------------------------------------------------
This transmission (including any attachments) may contain confidential information, privileged material (including material protected by the solicitor-client or other applicable privileges), or constitute non-public information. Any use of this information by anyone other than the intended recipient is prohibited. If you have received this transmission in error, please immediately reply to the sender and delete this information from your system. Use, dissemination, distribution, or reproduction of this transmission by unintended recipients is not authorized and may be unlawful.

[-- Warning: decoded text below may be mangled, UTF-8 assumed --]
[-- Attachment #2: libsbrk.c --]
[-- Type: text/x-csrc; name="libsbrk.c", Size: 2191 bytes --]

/**
 * @file    libsbrk.c
 * @brief   Naive implementation of sbrk()
 *
 * QNX doesn't support sbrk(), and heap-allocated data can reside anywhere in
 * the virtual address space. However, Emacs depdends on sbrk() for its own
 * allocator implementation, as well as for dumping a pre-loaded image.
 * This implementation reserves a non-backed region in the virtual address
 * space. A call to sbrk() that moves the break point causes the sub range
 * between the old and new break points to be backed by virtual memory.
 */


#include <sys/mman.h>
#include <stdint.h>
#include <errno.h>

#define SEGMENT_SIZE    1024 * 1024 * 1024

static void         *base_addr = MAP_FAILED;
static uintptr_t    break_addr;
static uintptr_t    max_addr;

/**
 * Moves the break point of the emulated data segment.
 * @param   increment   Amount of memory to add to the data segment
 * @return  Previous break point, if successful, -1 on failure
 */
void *
sbrk(intptr_t increment)
{
    if (base_addr == MAP_FAILED) {
        // Allocate a non-backed region of the address space.
        base_addr = mmap(0, SEGMENT_SIZE, PROT_NONE, MAP_PRIVATE | MAP_ANON,
                         -1, 0);
        if (base_addr == MAP_FAILED) {
            errno = ENOMEM;
            return (void *)-1;
        }

        break_addr = (uintptr_t)base_addr;
        max_addr = (uintptr_t)base_addr + SEGMENT_SIZE;
    }

    // Round up to a page size.
    increment = (increment + __PAGESIZE - 1) & ~(__PAGESIZE - 1);

    // Check for overflow.
    uintptr_t   new_addr = break_addr + increment;
    if (new_addr >= max_addr) {
        errno = ENOMEM;
        return (void *)-1;
    }

    // Only support incrementing the break point (though it's not hard to use
    // mprotect(PROT_NONE) to handle decrementing as well).
    if (new_addr <= break_addr) {
        return (void *)break_addr;
    }

    // Back the new sub-range.
    if (mmap((void *)break_addr, increment, PROT_READ | PROT_WRITE,
             MAP_FIXED | MAP_PRIVATE | MAP_ANON, -1, 0) == MAP_FAILED) {
        errno = ENOMEM;
        return (void *)-1;
    }

    void    *result = (void *)break_addr;
    break_addr = new_addr;
    return result;
}

             reply	other threads:[~2017-10-22 22:13 UTC|newest]

Thread overview: 17+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2017-10-22 22:13 Elad Lahav [this message]
2017-10-23  4:51 ` Emacs on QNX Paul Eggert
2017-10-23 11:27   ` Elad Lahav
2017-10-24  1:52     ` Elad Lahav
2017-10-24 20:14       ` Paul Eggert
2017-10-25  2:27         ` Elad Lahav
2017-10-26  3:52           ` Paul Eggert
2017-11-09 17:17             ` Elad Lahav
2017-11-09 17:23               ` Eli Zaretskii
2017-11-30 17:43                 ` Elad Lahav
2017-11-30 23:41                   ` Paul Eggert
2017-12-01  2:06                     ` Elad Lahav
2017-12-01  3:37                       ` Paul Eggert
2017-12-01 11:55                         ` Elad Lahav
2017-12-11  0:25                     ` Elad Lahav
2017-11-09 17:30               ` Noam Postavsky
2017-11-09 17:33                 ` Elad Lahav

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

  List information: https://www.gnu.org/software/emacs/

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=1508710435.8718.6.camel@blackberry.com \
    --to=elahav@blackberry.com \
    --cc=emacs-devel@gnu.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
Code repositories for project(s) associated with this public inbox

	https://git.savannah.gnu.org/cgit/emacs.git

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).