How can I get arm-none-eabi-gcc V6 via APT?

Asked by Stuart Longland on 2017-12-21

Just recently, there was an update to the GCC toolchain to version 7.

For whatever reason… this broke my code. I have a wrapper around `vsniprintf` that transmits syslog (RFC5424) messages, and this code instead of reporting log messages like this:

2017-12-21T02:40:00Z 11f47b5800124b00 scheduler Beginning poll at 1513824000
2017-12-21T02:40:00Z 11f47b5800124b00 scheduler Writing at 1513824000: 0x1ffe
2017-12-21T02:40:15Z 11f47b5800124b00 scheduler Beginning poll at 1513824015
2017-12-21T02:40:15Z 11f47b5800124b00 scheduler Writing at 1513824015: 0x1ffe
2017-12-21T02:40:30Z 11f47b5800124b00 scheduler Beginning poll at 1513824030
2017-12-21T02:40:30Z 11f47b5800124b00 scheduler Writing at 1513824030: 0x1ffe

started instead reporting log messages like this:

2017-12-21T02:46:32Z 11f47b5800124b00 scheduler Beginning poll at 536900368
2017-12-21T02:46:32Z 11f47b5800124b00 scheduler Writing at -7: 0x5a3b2086
2017-12-21T02:46:45Z 11f47b5800124b00 scheduler Beginning poll at 2300141
2017-12-21T02:46:45Z 11f47b5800124b00 scheduler Writing at 0: 0x5a3b2095
2017-12-21T02:47:00Z 11f47b5800124b00 scheduler Beginning poll at 2300141
2017-12-21T02:47:00Z 11f47b5800124b00 scheduler Writing at -7: 0x5a3b20a4

The function call that generates these messages looks like this:

  syslog_send(instance, SCHEDULER_FACILITY,
    SYSLOG_SEV_INFO,
    SCHEDULER_PROC,
    "Beginning poll at %ld",
    schedule_current);

  syslog_send(instance, SCHEDULER_FACILITY,
    SYSLOG_SEV_INFO,
    SCHEDULER_PROC,
    "Writing at %ld: 0x%04x",
    schedule_current, schedule_todo);

schedule_todo is a uint16_t… it is IMPOSSIBLE for it to have the value 0x5a3b20a4. schedule_current is a time_t. The code behind `syslog_send`:

/*!
 * Send a syslog message (varadic version).
 */
static inline int syslog_send(otInstance* instance,
  uint8_t facility, uint8_t severity,
  const char* app, const char* fmt, ...) {
 int res;
 va_list fmt_args;
 va_start(fmt_args, fmt);
 res = syslog_send_va(instance, facility, severity, app, fmt, fmt_args);
 va_end(fmt_args);
 return res;
}

/*!
 * Send a syslog message.
 */
int syslog_send_va(otInstance* instance,
  uint8_t facility, uint8_t severity,
  const char* app, const char* fmt, va_list fmt_args) {

 /* Retrieve the current system time */
 struct timeval tv;
 int res = gettimeofday(&tv, NULL);
 if (res < 0) {
  return res;
 }

 char buffer[SYSLOG_BUF_SZ];
 int16_t sz = syslog_format(instance, buffer, sizeof(buffer),
   tv.tv_sec, facility, severity, app, fmt, fmt_args);
 if (sz < 0) {
  return sz;
 }

/*!
 * Format a received message into a log buffer and return its size.
 */
static int16_t syslog_format(
  otInstance* instance,
  char* buffer, uint16_t buf_sz,
  time_t timestamp, uint8_t facility, uint8_t severity,
  const char* app, const char* fmt, va_list fmt_args) {
 /* Sum of bytes written */
 int16_t sum = 0;

 /* Converted timestamp */
 struct tm tm;
 if (!gmtime_r(&timestamp, &tm)) {
  /* Invalid timestamp arguments given */
  return -errno;
 }

#ifdef SYSLOG_TRACE
#ifdef SYSLOG_TRACE_FORMAT
 iprintf("%s:%d Format message %s\r\n",
  __FILE__, __LINE__, fmt);
#endif
#endif

 /* Format the message header first. */
 int fmt_sz = sniprintf(buffer, buf_sz,
   "<%d>1 %04d-%02d-%02dT%02d:%02d:%02dZ ",
   /* Priority value */
   (facility << 3) | (severity & 0x07),
   /* Timestamp */
   tm.tm_year + 1900,
   tm.tm_mon + 1,
   tm.tm_mday,
   tm.tm_hour,
   tm.tm_min,
   tm.tm_sec);

#ifdef SYSLOG_TRACE
#ifdef SYSLOG_TRACE_FORMAT
 iprintf("%s:%d Size: %d Buffer: %s\r\n",
  __FILE__, __LINE__, fmt_sz, buffer);
#endif
#endif

 buf_sz -= fmt_sz;
 buffer += fmt_sz;
 sum += fmt_sz;

 /* Append hostname */
 hostname(instance, buffer, buf_sz);
#ifdef SYSLOG_TRACE
#ifdef SYSLOG_TRACE_FORMAT
 iprintf("%s:%d Size: %d Buffer: %s\r\n",
  __FILE__, __LINE__, HOSTNAME_LEN, buffer);
#endif
#endif
 buffer += HOSTNAME_LEN;
 buf_sz -= HOSTNAME_LEN;
 sum += HOSTNAME_LEN;

 /* Append remainder of header */
 fmt_sz = sniprintf(buffer, buf_sz,
   " %s - - - ", app);
#ifdef SYSLOG_TRACE
#ifdef SYSLOG_TRACE_FORMAT
 iprintf("%s:%d Size: %d Buffer: %s\r\n",
  __FILE__, __LINE__, fmt_sz, buffer);
#endif
#endif

 buffer += fmt_sz;
 buf_sz -= fmt_sz;
 sum += fmt_sz;

 /* Append message */
 fmt_sz = vsniprintf(buffer, buf_sz, fmt, fmt_args); /* <-- vsniprintf is HERE */
#ifdef SYSLOG_TRACE
#ifdef SYSLOG_TRACE_FORMAT
 iprintf("%s:%d Size: %d Buffer: %s\r\n",
  __FILE__, __LINE__, fmt_sz, buffer);
#endif
#endif
 sum += fmt_sz;

 /* We're done */
#ifdef SYSLOG_TRACE
#ifdef SYSLOG_TRACE_FORMAT
 iprintf("%s:%d Total %u\r\n",
  __FILE__, __LINE__, sum);
#endif
#endif
 return sum;
}

It is clear that, at the very least, vsniprintf and/or the implementation behind stdarg.h… is misbehaving badly. Possibly other things too: maybe the optimiser is being a bit overzealous, I don't know.

I can reproduce the same problem with both the Debian package version of arm-none-eabi-gcc v7 (on Debian Jessie), and the tarball binary from the upstream developers (on Gentoo). Rolling back to gcc v6 (on my Gentoo-based workstation) fixes the problem.

Unfortunately, looking in the repository, I do not see a package for GCC v6, and I do not have the time to migrate the code to GCC v7 prior to my workplace closing for the year (tomorrow around 11:00 UTC+10). If the old package were still in the repository, it'd be possible for me to work-around things by just forcing `apt-get` to install the older version. Without that there, I can do nothing, and mirroring the APT repository makes a mockery of using it in the first place.

It is not possible to download the tarball automatically as pointing `wget` or `curl` at the links that ARM provide simply gives me the HTML page that the file is linked to… and running a web browser is not viable from within a CI environment. The URI is also a moving target. The CI environment builds the following Docker image:

https://hub.docker.com/r/vrtsystems/widesky-openthread-build-env/

… which is then used to build our code. If you could point me to the APT repository where you keep the older binaries, that would be most appreciated.

Question information

Language:
English Edit question
Status:
Answered
For:
GNU Arm Embedded Toolchain Edit question
Assignee:
No assignee Edit question
Last query:
2017-12-21
Last reply:
2018-01-02
Stuart Longland (redhatter) said : #1

For the record, this is the full syslog code:
https://gist.github.com/sjlongland/d4c08e9bf370ae525afb4831ef082ecd

Christopher Haster (chaster) said : #2

We are also running into this issue. Is it possible to provide GCC v6 on the ppa? That would make it possible to install GCC by version until codebases can be updated.

sudo apt-get install 'gcc-arm-embedded=6*'

Tejas Belagod (belagod-tejas) said : #3

Hi,

Sorry for the late reply. Can you wget from

https://developer.arm.com/-/media/Files/downloads/gnu-rm/7-2017q4/gcc-arm-none-eabi-7-2017-q4-major-linux.tar.bz2?revision=375265d4-e9b5-41c8-bf23-56cbe927e156?product=GNU%20Arm%20Embedded%20Toolchain,64-bit,,Linux,7-2017-q4-major

for the time being for your CI?

There is no way currently to fall back to a previous PPA version - this is partly a limitation of the PPA system as I understand it. We could investigate versioning it for the next release.

Meantime, it would help us immensely if you could give us a minimal example test case that reproduces your issue.

Thanks,
Tejas.

Can you help with this problem?

Provide an answer of your own, or ask Stuart Longland for more information if necessary.

To post a message you must log in.