void
subsegs_print_statistics (FILE *file)
{
  frchainS *frchp;
  asection *s;

  fprintf (file, "frag chains:\n");
  for (s = stdoutput->sections; s; s = s->next)
    {
      segment_info_type *seginfo;

      /* Skip gas-internal sections.  */
      if (segment_name (s)[0] == '*')
	continue;

      seginfo = seg_info (s);
      if (!seginfo)
	continue;

      for (frchp = seginfo->frchainP; frchp; frchp = frchp->frch_next)
	{
	  int count = 0;
	  fragS *fragp;

	  for (fragp = frchp->frch_root; fragp; fragp = fragp->fr_next)
	    count++;

	  fprintf (file, "\n");
	  fprintf (file, "\t%p %-10s\t%10d frags\n", (void *) frchp,
		   segment_name (s), count);
	}
    }
}
Exemple #2
0
static void
out_debug_line (segT line_seg)
{
  expressionS exp;
  symbolS *prologue_end;
  symbolS *line_end;
  struct line_seg *s;
  int sizeof_offset;

  sizeof_offset = out_header (line_seg, &exp);
  line_end = exp.X_add_symbol;

  /* Version.  */
  out_two (DWARF2_VERSION);

  /* Length of the prologue following this length.  */
  prologue_end = symbol_temp_make ();
  exp.X_add_symbol = prologue_end;
  exp.X_add_number = - (4 + 2 + 4);
  emit_expr (&exp, sizeof_offset);

  /* Parameters of the state machine.  */
  out_byte (DWARF2_LINE_MIN_INSN_LENGTH);
  out_byte (DWARF2_LINE_DEFAULT_IS_STMT);
  out_byte (DWARF2_LINE_BASE);
  out_byte (DWARF2_LINE_RANGE);
  out_byte (DWARF2_LINE_OPCODE_BASE);

  /* Standard opcode lengths.  */
  out_byte (0);			/* DW_LNS_copy */
  out_byte (1);			/* DW_LNS_advance_pc */
  out_byte (1);			/* DW_LNS_advance_line */
  out_byte (1);			/* DW_LNS_set_file */
  out_byte (1);			/* DW_LNS_set_column */
  out_byte (0);			/* DW_LNS_negate_stmt */
  out_byte (0);			/* DW_LNS_set_basic_block */
  out_byte (0);			/* DW_LNS_const_add_pc */
  out_byte (1);			/* DW_LNS_fixed_advance_pc */
  out_byte (0);			/* DW_LNS_set_prologue_end */
  out_byte (0);			/* DW_LNS_set_epilogue_begin */
  out_byte (1);			/* DW_LNS_set_isa */

  out_file_list ();

  symbol_set_value_now (prologue_end);

  /* For each section, emit a statement program.  */
  for (s = all_segs; s; s = s->next)
    if (SEG_NORMAL (s->seg))
      process_entries (s->seg, s->head->head);
    else
      as_warn ("dwarf line number information for %s ignored",
	       segment_name (s->seg));

  symbol_set_value_now (line_end);
}
Exemple #3
0
int pa_shm_attach(pa_shm *m, unsigned id, bool writable) {
    char fn[32];
    int fd = -1;
    int prot;
    struct stat st;

    pa_assert(m);

    segment_name(fn, sizeof(fn), m->id = id);

    if ((fd = shm_open(fn, writable ? O_RDWR : O_RDONLY, 0)) < 0) {
        if (errno != EACCES && errno != ENOENT)
            pa_log("shm_open() failed: %s", pa_cstrerror(errno));
        goto fail;
    }

    if (fstat(fd, &st) < 0) {
        pa_log("fstat() failed: %s", pa_cstrerror(errno));
        goto fail;
    }

    if (st.st_size <= 0 ||
        st.st_size > (off_t) (MAX_SHM_SIZE+SHM_MARKER_SIZE) ||
        PA_ALIGN((size_t) st.st_size) != (size_t) st.st_size) {
        pa_log("Invalid shared memory segment size");
        goto fail;
    }

    m->size = (size_t) st.st_size;

    prot = writable ? PROT_READ | PROT_WRITE : PROT_READ;
    if ((m->ptr = mmap(NULL, PA_PAGE_ALIGN(m->size), prot, MAP_SHARED, fd, (off_t) 0)) == MAP_FAILED) {
        pa_log("mmap() failed: %s", pa_cstrerror(errno));
        goto fail;
    }

    m->do_unlink = false;
    m->shared = true;

    pa_assert_se(pa_close(fd) == 0);

    return 0;

fail:
    if (fd >= 0)
        pa_close(fd);

    return -1;
}
Exemple #4
0
int pa_shm_attach_ro(pa_shm *m, unsigned id) {
    char fn[32];
    int fd = -1;
    struct stat st;

    pa_assert(m);

    segment_name(fn, sizeof(fn), m->id = id);

    if ((fd = shm_open(fn, O_RDONLY, 0)) < 0) {
        if (errno != EACCES)
            pa_log("shm_open() failed: %s", pa_cstrerror(errno));
        goto fail;
    }

    if (fstat(fd, &st) < 0) {
        pa_log("fstat() failed: %s", pa_cstrerror(errno));
        goto fail;
    }

    if (st.st_size <= 0 ||
        st.st_size > (off_t) (MAX_SHM_SIZE+SHM_MARKER_SIZE) ||
        PA_ALIGN((size_t) st.st_size) != (size_t) st.st_size) {
        pa_log("Invalid shared memory segment size");
        goto fail;
    }

    m->size = (size_t) st.st_size;

    if ((m->ptr = mmap(NULL, PA_PAGE_ALIGN(m->size), PROT_READ, MAP_SHARED, fd, (off_t) 0)) == MAP_FAILED) {
        pa_log("mmap() failed: %s", pa_cstrerror(errno));
        goto fail;
    }

    m->do_unlink = FALSE;
    m->shared = TRUE;

    pa_assert_se(pa_close(fd) == 0);

    return 0;

fail:
    if (fd >= 0)
        pa_close(fd);

    return -1;
}
Exemple #5
0
void pa_shm_free(pa_shm *m) {
    pa_assert(m);
    pa_assert(m->ptr);
    pa_assert(m->size > 0);

#ifdef MAP_FAILED
    pa_assert(m->ptr != MAP_FAILED);
#endif

    if (m->type == PA_MEM_TYPE_PRIVATE) {
        privatemem_free(m);
        goto finish;
    }

#if defined(HAVE_SHM_OPEN) || defined(HAVE_MEMFD)
    if (munmap(m->ptr, PA_PAGE_ALIGN(m->size)) < 0)
        pa_log("munmap() failed: %s", pa_cstrerror(errno));

#ifdef HAVE_SHM_OPEN
    if (m->type == PA_MEM_TYPE_SHARED_POSIX && m->do_unlink) {
        char fn[32];

        segment_name(fn, sizeof(fn), m->id);
        if (shm_unlink(fn) < 0)
            pa_log(" shm_unlink(%s) failed: %s", fn, pa_cstrerror(errno));
    }
#endif
#ifdef HAVE_MEMFD
    if (m->type == PA_MEM_TYPE_SHARED_MEMFD && m->fd != -1)
        pa_assert_se(pa_close(m->fd) == 0);
#endif

#else
    /* We shouldn't be here without shm or memfd support */
    pa_assert_not_reached();
#endif

finish:
    pa_zero(*m);
}
Exemple #6
0
void pa_shm_free(pa_shm *m) {
    pa_assert(m);
    pa_assert(m->ptr);
    pa_assert(m->size > 0);

#ifdef MAP_FAILED
    pa_assert(m->ptr != MAP_FAILED);
#endif

    if (!m->shared) {
#ifdef MAP_ANONYMOUS
        if (munmap(m->ptr, m->size) < 0)
            pa_log("munmap() failed: %s", pa_cstrerror(errno));
#elif defined(HAVE_POSIX_MEMALIGN)
        free(m->ptr);
#else
        pa_xfree(m->ptr);
#endif
    } else {
#ifdef HAVE_SHM_OPEN
        if (munmap(m->ptr, PA_PAGE_ALIGN(m->size)) < 0)
            pa_log("munmap() failed: %s", pa_cstrerror(errno));

        if (m->do_unlink) {
            char fn[32];

            segment_name(fn, sizeof(fn), m->id);

            if (shm_unlink(fn) < 0)
                pa_log(" shm_unlink(%s) failed: %s", fn, pa_cstrerror(errno));
        }
#else
        /* We shouldn't be here without shm support */
        pa_assert_not_reached();
#endif
    }

    pa_zero(*m);
}
Exemple #7
0
int pa_shm_cleanup(void) {

#ifdef HAVE_SHM_OPEN
#ifdef SHM_PATH
    DIR *d;
    struct dirent *de;

    if (!(d = opendir(SHM_PATH))) {
        pa_log_warn("Failed to read "SHM_PATH": %s", pa_cstrerror(errno));
        return -1;
    }

    while ((de = readdir(d))) {
        pa_shm seg;
        unsigned id;
        pid_t pid;
        char fn[128];
        struct shm_marker *m;

#if defined(__sun)
        if (strncmp(de->d_name, ".SHMDpulse-shm-", SHM_ID_LEN))
#else
        if (strncmp(de->d_name, "pulse-shm-", SHM_ID_LEN))
#endif
            continue;

        if (pa_atou(de->d_name + SHM_ID_LEN, &id) < 0)
            continue;

        if (pa_shm_attach(&seg, id, false) < 0)
            continue;

        if (seg.size < SHM_MARKER_SIZE) {
            pa_shm_free(&seg);
            continue;
        }

        m = (struct shm_marker*) ((uint8_t*) seg.ptr + seg.size - SHM_MARKER_SIZE);

        if (pa_atomic_load(&m->marker) != SHM_MARKER) {
            pa_shm_free(&seg);
            continue;
        }

        if (!(pid = (pid_t) pa_atomic_load(&m->pid))) {
            pa_shm_free(&seg);
            continue;
        }

        if (kill(pid, 0) == 0 || errno != ESRCH) {
            pa_shm_free(&seg);
            continue;
        }

        pa_shm_free(&seg);

        /* Ok, the owner of this shms segment is dead, so, let's remove the segment */
        segment_name(fn, sizeof(fn), id);

        if (shm_unlink(fn) < 0 && errno != EACCES && errno != ENOENT)
            pa_log_warn("Failed to remove SHM segment %s: %s\n", fn, pa_cstrerror(errno));
    }

    closedir(d);
#endif /* SHM_PATH */
#endif /* HAVE_SHM_OPEN */

    return 0;
}
Exemple #8
0
int pa_shm_create_rw(pa_shm *m, size_t size, bool shared, mode_t mode) {
#ifdef HAVE_SHM_OPEN
    char fn[32];
    int fd = -1;
#endif

    pa_assert(m);
    pa_assert(size > 0);
    pa_assert(size <= MAX_SHM_SIZE);
    pa_assert(!(mode & ~0777));
    pa_assert(mode >= 0600);

    /* Each time we create a new SHM area, let's first drop all stale
     * ones */
    pa_shm_cleanup();

    /* Round up to make it page aligned */
    size = PA_PAGE_ALIGN(size);

    if (!shared) {
        m->id = 0;
        m->size = size;

#ifdef MAP_ANONYMOUS
        if ((m->ptr = mmap(NULL, m->size, PROT_READ|PROT_WRITE, MAP_ANONYMOUS|MAP_PRIVATE, -1, (off_t) 0)) == MAP_FAILED) {
            pa_log("mmap() failed: %s", pa_cstrerror(errno));
            goto fail;
        }
#elif defined(HAVE_POSIX_MEMALIGN)
        {
            int r;

            if ((r = posix_memalign(&m->ptr, PA_PAGE_SIZE, size)) < 0) {
                pa_log("posix_memalign() failed: %s", pa_cstrerror(r));
                goto fail;
            }
        }
#else
        m->ptr = pa_xmalloc(m->size);
#endif

        m->do_unlink = false;

    } else {
#ifdef HAVE_SHM_OPEN
        struct shm_marker *marker;

        pa_random(&m->id, sizeof(m->id));
        segment_name(fn, sizeof(fn), m->id);

        if ((fd = shm_open(fn, O_RDWR|O_CREAT|O_EXCL, mode)) < 0) {
            pa_log("shm_open() failed: %s", pa_cstrerror(errno));
            goto fail;
        }

        m->size = size + SHM_MARKER_SIZE;

        if (ftruncate(fd, (off_t) m->size) < 0) {
            pa_log("ftruncate() failed: %s", pa_cstrerror(errno));
            goto fail;
        }

#ifndef MAP_NORESERVE
#define MAP_NORESERVE 0
#endif

        if ((m->ptr = mmap(NULL, PA_PAGE_ALIGN(m->size), PROT_READ|PROT_WRITE, MAP_SHARED|MAP_NORESERVE, fd, (off_t) 0)) == MAP_FAILED) {
            pa_log("mmap() failed: %s", pa_cstrerror(errno));
            goto fail;
        }

        /* We store our PID at the end of the shm block, so that we
         * can check for dead shm segments later */
        marker = (struct shm_marker*) ((uint8_t*) m->ptr + m->size - SHM_MARKER_SIZE);
        pa_atomic_store(&marker->pid, (int) getpid());
        pa_atomic_store(&marker->marker, SHM_MARKER);

        pa_assert_se(pa_close(fd) == 0);
        m->do_unlink = true;
#else
        goto fail;
#endif
    }

    m->shared = shared;

    return 0;

fail:

#ifdef HAVE_SHM_OPEN
    if (fd >= 0) {
        shm_unlink(fn);
        pa_close(fd);
    }
#endif

    return -1;
}
Exemple #9
0
static void
list_symbol_table (void)
{
  extern symbolS *symbol_rootP;
  int got_some = 0;

  symbolS *ptr;
  eject = 1;
  listing_page (NULL);

  for (ptr = symbol_rootP; ptr != (symbolS *) NULL; ptr = symbol_next (ptr))
    {
      if (SEG_NORMAL (S_GET_SEGMENT (ptr))
	  || S_GET_SEGMENT (ptr) == absolute_section)
	{
	  /* Don't report section symbols.  They are not interesting.  */
	  if (symbol_section_p (ptr))
	    continue;

	  if (S_GET_NAME (ptr))
	    {
	      char buf[30], fmt[8];
	      valueT val = S_GET_VALUE (ptr);

	      /* @@ Note that this is dependent on the compilation options,
		 not solely on the target characteristics.  */
	      if (sizeof (val) == 4 && sizeof (int) == 4)
		sprintf (buf, "%08lx", (unsigned long) val);
	      else if (sizeof (val) <= sizeof (unsigned long))
		{
		  sprintf (fmt, "%%0%lulx",
			   (unsigned long) (sizeof (val) * 2));
		  sprintf (buf, fmt, (unsigned long) val);
		}
#if defined (BFD64)
	      else if (sizeof (val) > 4)
		sprintf_vma (buf, val);
#endif
	      else
		abort ();

	      if (!got_some)
		{
		  fprintf (list_file, "DEFINED SYMBOLS\n");
		  on_page++;
		  got_some = 1;
		}

	      if (symbol_get_frag (ptr) && symbol_get_frag (ptr)->line)
		{
		  fprintf (list_file, "%20s:%-5d  %s:%s %s\n",
			   symbol_get_frag (ptr)->line->file->filename,
			   symbol_get_frag (ptr)->line->line,
			   segment_name (S_GET_SEGMENT (ptr)),
			   buf, S_GET_NAME (ptr));
		}
	      else
		{
		  fprintf (list_file, "%33s:%s %s\n",
			   segment_name (S_GET_SEGMENT (ptr)),
			   buf, S_GET_NAME (ptr));
		}

	      on_page++;
	      listing_page (NULL);
	    }
	}

    }
  if (!got_some)
    {
      fprintf (list_file, "NO DEFINED SYMBOLS\n");
      on_page++;
    }
  emit_line (NULL, "\n");

  got_some = 0;

  for (ptr = symbol_rootP; ptr != (symbolS *) NULL; ptr = symbol_next (ptr))
    {
      if (S_GET_NAME (ptr) && strlen (S_GET_NAME (ptr)) != 0)
	{
	  if (S_GET_SEGMENT (ptr) == undefined_section)
	    {
	      if (!got_some)
		{
		  got_some = 1;

		  emit_line (NULL, "UNDEFINED SYMBOLS\n");
		}

	      emit_line (NULL, "%s\n", S_GET_NAME (ptr));
	    }
	}
    }

  if (!got_some)
    emit_line (NULL, "NO UNDEFINED SYMBOLS\n");
}
Exemple #10
0
void
listing_newline (char *ps)
{
  char *file;
  unsigned int line;
  static unsigned int last_line = 0xffff;
  static char *last_file = NULL;
  list_info_type *new_i = NULL;

  if (listing == 0)
    return;

  if (now_seg == absolute_section)
    return;

#ifdef OBJ_ELF
  /* In ELF, anything in a section beginning with .debug or .line is
     considered to be debugging information.  This includes the
     statement which switches us into the debugging section, which we
     can only set after we are already in the debugging section.  */
  if ((listing & LISTING_NODEBUG) != 0
      && listing_tail != NULL
      && ! listing_tail->debugging)
    {
      const char *segname;

      segname = segment_name (now_seg);
      if (strncmp (segname, ".debug", sizeof ".debug" - 1) == 0
	  || strncmp (segname, ".line", sizeof ".line" - 1) == 0)
	listing_tail->debugging = 1;
    }
#endif

  as_where (&file, &line);
  if (ps == NULL)
    {
      if (line == last_line
	  && !(last_file && file && filename_cmp (file, last_file)))
	return;

      new_i = (list_info_type *) xmalloc (sizeof (list_info_type));

      /* Detect if we are reading from stdin by examining the file
	 name returned by as_where().

	 [FIXME: We rely upon the name in the strcmp below being the
	 same as the one used by input_scrub_new_file(), if that is
	 not true, then this code will fail].

	 If we are reading from stdin, then we need to save each input
	 line here (assuming of course that we actually have a line of
	 input to read), so that it can be displayed in the listing
	 that is produced at the end of the assembly.  */
      if (strcmp (file, _("{standard input}")) == 0
	  && input_line_pointer != NULL)
	{
	  char *copy;
	  int len;
	  int seen_quote = 0;
	  int seen_slash = 0;

	  for (copy = input_line_pointer;
	       *copy && (seen_quote
			 || is_end_of_line [(unsigned char) *copy] != 1);
	       copy++)
	    {
	      if (seen_slash)
		seen_slash = 0;
	      else if (*copy == '\\')
		seen_slash = 1;
	      else if (*copy == '"')
		seen_quote = !seen_quote;
	    }

	  len = copy - input_line_pointer + 1;

	  copy = (char *) xmalloc (len);

	  if (copy != NULL)
	    {
	      char *src = input_line_pointer;
	      char *dest = copy;

	      while (--len)
		{
		  unsigned char c = *src++;

		  /* Omit control characters in the listing.  */
		  if (!ISCNTRL (c))
		    *dest++ = c;
		}

	      *dest = 0;
	    }

	  new_i->line_contents = copy;
	}
      else
	new_i->line_contents = NULL;
    }
  else
    {
      new_i = (list_info_type *) xmalloc (sizeof (list_info_type));
      new_i->line_contents = ps;
    }

  last_line = line;
  last_file = file;

  new_frag ();

  if (listing_tail)
    listing_tail->next = new_i;
  else
    head = new_i;

  listing_tail = new_i;

  new_i->frag = frag_now;
  new_i->line = line;
  new_i->file = file_info (file);
  new_i->next = (list_info_type *) NULL;
  new_i->messages = NULL;
  new_i->last_message = NULL;
  new_i->edict = EDICT_NONE;
  new_i->hll_file = (file_info_type *) NULL;
  new_i->hll_line = 0;
  new_i->debugging = 0;

  new_frag ();

#ifdef OBJ_ELF
  /* In ELF, anything in a section beginning with .debug or .line is
     considered to be debugging information.  */
  if ((listing & LISTING_NODEBUG) != 0)
    {
      const char *segname;

      segname = segment_name (now_seg);
      if (strncmp (segname, ".debug", sizeof ".debug" - 1) == 0
	  || strncmp (segname, ".line", sizeof ".line" - 1) == 0)
	new_i->debugging = 1;
    }
#endif
}
Exemple #11
0
int
check_eh_frame (expressionS *exp, unsigned int *pnbytes)
{
  struct frame_data
  {
    enum frame_state state;

    int cie_info_ok;
    struct cie_info cie_info;

    symbolS *size_end_sym;
    fragS *loc4_frag;
    int loc4_fix;

    int aug_size;
    int aug_shift;
  };

  static struct frame_data eh_frame_data;
  static struct frame_data debug_frame_data;
  struct frame_data *d;

  /* Don't optimize.  */
  if (flag_traditional_format)
    return 0;

#ifdef md_allow_eh_opt
  if (! md_allow_eh_opt)
    return 0;
#endif

  /* Select the proper section data.  */
  if (strncmp (segment_name (now_seg), ".eh_frame", 9) == 0
      && segment_name (now_seg)[9] != '_')
    d = &eh_frame_data;
  else if (strncmp (segment_name (now_seg), ".debug_frame", 12) == 0)
    d = &debug_frame_data;
  else
    return 0;

  if (d->state >= state_saw_size && S_IS_DEFINED (d->size_end_sym))
    {
      /* We have come to the end of the CIE or FDE.  See below where
         we set saw_size.  We must check this first because we may now
         be looking at the next size.  */
      d->state = state_idle;
    }

  switch (d->state)
    {
    case state_idle:
      if (*pnbytes == 4)
	{
	  /* This might be the size of the CIE or FDE.  We want to know
	     the size so that we don't accidentally optimize across an FDE
	     boundary.  We recognize the size in one of two forms: a
	     symbol which will later be defined as a difference, or a
	     subtraction of two symbols.  Either way, we can tell when we
	     are at the end of the FDE because the symbol becomes defined
	     (in the case of a subtraction, the end symbol, from which the
	     start symbol is being subtracted).  Other ways of describing
	     the size will not be optimized.  */
	  if ((exp->X_op == O_symbol || exp->X_op == O_subtract)
	      && ! S_IS_DEFINED (exp->X_add_symbol))
	    {
	      d->state = state_saw_size;
	      d->size_end_sym = exp->X_add_symbol;
	    }
	}
      break;

    case state_saw_size:
    case state_saw_cie_offset:
      /* Assume whatever form it appears in, it appears atomically.  */
      d->state = (enum frame_state) (d->state + 1);
      break;

    case state_saw_pc_begin:
      /* Decide whether we should see an augmentation.  */
      if (! d->cie_info_ok
	  && ! (d->cie_info_ok = get_cie_info (&d->cie_info)))
	d->state = state_error;
      else if (d->cie_info.z_augmentation)
	{
	  d->state = state_seeing_aug_size;
	  d->aug_size = 0;
	  d->aug_shift = 0;
	}
      else
	d->state = state_wait_loc4;
      break;

    case state_seeing_aug_size:
      /* Bytes == -1 means this comes from an leb128 directive.  */
      if ((int)*pnbytes == -1 && exp->X_op == O_constant)
	{
	  d->aug_size = exp->X_add_number;
	  d->state = state_skipping_aug;
	}
      else if (*pnbytes == 1 && exp->X_op == O_constant)
	{
	  unsigned char byte = exp->X_add_number;
	  d->aug_size |= (byte & 0x7f) << d->aug_shift;
	  d->aug_shift += 7;
	  if ((byte & 0x80) == 0)
	    d->state = state_skipping_aug;
	}
      else
	d->state = state_error;
      if (d->state == state_skipping_aug && d->aug_size == 0)
	d->state = state_wait_loc4;
      break;

    case state_skipping_aug:
      if ((int)*pnbytes < 0)
	d->state = state_error;
      else
	{
	  int left = (d->aug_size -= *pnbytes);
	  if (left == 0)
	    d->state = state_wait_loc4;
	  else if (left < 0)
	    d->state = state_error;
	}
      break;

    case state_wait_loc4:
      if (*pnbytes == 1
	  && exp->X_op == O_constant
	  && exp->X_add_number == DW_CFA_advance_loc4)
	{
	  /* This might be a DW_CFA_advance_loc4.  Record the frag and the
	     position within the frag, so that we can change it later.  */
	  frag_grow (1);
	  d->state = state_saw_loc4;
	  d->loc4_frag = frag_now;
	  d->loc4_fix = frag_now_fix ();
	}
      break;

    case state_saw_loc4:
      d->state = state_wait_loc4;
      if (*pnbytes != 4)
	break;
      if (exp->X_op == O_constant)
	{
	  /* This is a case which we can optimize.  The two symbols being
	     subtracted were in the same frag and the expression was
	     reduced to a constant.  We can do the optimization entirely
	     in this function.  */
	  if (exp->X_add_number < 0x40)
	    {
	      d->loc4_frag->fr_literal[d->loc4_fix]
		= DW_CFA_advance_loc | exp->X_add_number;
	      /* No more bytes needed.  */
	      return 1;
	    }
	  else if (exp->X_add_number < 0x100)
	    {
	      d->loc4_frag->fr_literal[d->loc4_fix] = DW_CFA_advance_loc1;
	      *pnbytes = 1;
	    }
	  else if (exp->X_add_number < 0x10000)
	    {
	      d->loc4_frag->fr_literal[d->loc4_fix] = DW_CFA_advance_loc2;
	      *pnbytes = 2;
	    }
	}
      else if (exp->X_op == O_subtract && d->cie_info.code_alignment == 1)
	{
	  /* This is a case we can optimize.  The expression was not
	     reduced, so we can not finish the optimization until the end
	     of the assembly.  We set up a variant frag which we handle
	     later.  */
	  frag_var (rs_cfa, 4, 0, 1 << 3, make_expr_symbol (exp),
		    d->loc4_fix, (char *) d->loc4_frag);
	  return 1;
	}
      else if ((exp->X_op == O_divide
		|| exp->X_op == O_right_shift)
	       && d->cie_info.code_alignment > 1)
	{
	  if (symbol_symbolS (exp->X_add_symbol)
	      && symbol_constant_p (exp->X_op_symbol)
	      && S_GET_SEGMENT (exp->X_op_symbol) == absolute_section
	      && ((exp->X_op == O_divide
		   ? *symbol_X_add_number (exp->X_op_symbol)
		   : (offsetT) 1 << *symbol_X_add_number (exp->X_op_symbol))
		  == (offsetT) d->cie_info.code_alignment))
	    {
	      expressionS *symval;

	      symval = symbol_get_value_expression (exp->X_add_symbol);
	      if (symval->X_op == O_subtract)
		{
		  /* This is a case we can optimize as well.  The
		     expression was not reduced, so we can not finish
		     the optimization until the end of the assembly.
		     We set up a variant frag which we handle later.  */
		  frag_var (rs_cfa, 4, 0, d->cie_info.code_alignment << 3,
			    make_expr_symbol (symval),
			    d->loc4_fix, (char *) d->loc4_frag);
		  return 1;
		}
	    }
	}
      break;

    case state_error:
      /* Just skipping everything.  */
      break;
    }

  return 0;
}
Exemple #12
0
static int
get_cie_info (struct cie_info *info)
{
  fragS *f;
  fixS *fix;
  int offset;
  char CIE_id;
  char augmentation[10];
  int iaug;
  int code_alignment = 0;

  /* We should find the CIE at the start of the section.  */

  f = seg_info (now_seg)->frchainP->frch_root;
  fix = seg_info (now_seg)->frchainP->fix_root;

  /* Look through the frags of the section to find the code alignment.  */

  /* First make sure that the CIE Identifier Tag is 0/-1.  */

  if (strncmp (segment_name (now_seg), ".debug_frame", 12) == 0)
    CIE_id = (char)0xff;
  else
    CIE_id = 0;

  offset = 4;
  while (f != NULL && offset >= f->fr_fix)
    {
      offset -= f->fr_fix;
      f = f->fr_next;
    }
  if (f == NULL
      || f->fr_fix - offset < 4
      || f->fr_literal[offset] != CIE_id
      || f->fr_literal[offset + 1] != CIE_id
      || f->fr_literal[offset + 2] != CIE_id
      || f->fr_literal[offset + 3] != CIE_id)
    return 0;

  /* Next make sure the CIE version number is 1.  */

  offset += 4;
  while (f != NULL && offset >= f->fr_fix)
    {
      offset -= f->fr_fix;
      f = f->fr_next;
    }
  if (f == NULL
      || f->fr_fix - offset < 1
      || f->fr_literal[offset] != 1)
    return 0;

  /* Skip the augmentation (a null terminated string).  */

  iaug = 0;
  ++offset;
  while (1)
    {
      while (f != NULL && offset >= f->fr_fix)
	{
	  offset -= f->fr_fix;
	  f = f->fr_next;
	}
      if (f == NULL)
	return 0;

      while (offset < f->fr_fix && f->fr_literal[offset] != '\0')
	{
	  if ((size_t) iaug < (sizeof augmentation) - 1)
	    {
	      augmentation[iaug] = f->fr_literal[offset];
	      ++iaug;
	    }
	  ++offset;
	}
      if (offset < f->fr_fix)
	break;
    }
  ++offset;
  while (f != NULL && offset >= f->fr_fix)
    {
      offset -= f->fr_fix;
      f = f->fr_next;
    }
  if (f == NULL)
    return 0;

  augmentation[iaug] = '\0';
  if (augmentation[0] == '\0')
    {
      /* No augmentation.  */
    }
  else if (strcmp (augmentation, "eh") == 0)
    {
      /* We have to skip a pointer.  Unfortunately, we don't know how
	 large it is.  We find out by looking for a matching fixup.  */
      while (fix != NULL
	     && (fix->fx_frag != f || fix->fx_where != offset))
	fix = fix->fx_next;
      if (fix == NULL)
	offset += 4;
      else
	offset += fix->fx_size;
      while (f != NULL && offset >= f->fr_fix)
	{
	  offset -= f->fr_fix;
	  f = f->fr_next;
	}
      if (f == NULL)
	return 0;
    }
  else if (augmentation[0] != 'z')
    return 0;

  /* We're now at the code alignment factor, which is a ULEB128.  If
     it isn't a single byte, forget it.  */

  code_alignment = f->fr_literal[offset] & 0xff;
  if ((code_alignment & 0x80) != 0)
    code_alignment = 0;

  info->code_alignment = code_alignment;
  info->z_augmentation = (augmentation[0] == 'z');

  return 1;
}
Exemple #13
0
static int shm_attach(pa_shm *m, pa_mem_type_t type, unsigned id, int memfd_fd, bool writable, bool for_cleanup) {
#if defined(HAVE_SHM_OPEN) || defined(HAVE_MEMFD)
    char fn[32];
    int fd = -1;
    int prot;
    struct stat st;

    pa_assert(m);

    switch (type) {
#ifdef HAVE_SHM_OPEN
    case PA_MEM_TYPE_SHARED_POSIX:
        pa_assert(memfd_fd == -1);
        segment_name(fn, sizeof(fn), id);
        if ((fd = shm_open(fn, writable ? O_RDWR : O_RDONLY, 0)) < 0) {
            if ((errno != EACCES && errno != ENOENT) || !for_cleanup)
                pa_log("shm_open() failed: %s", pa_cstrerror(errno));
            goto fail;
        }
        break;
#endif
#ifdef HAVE_MEMFD
    case PA_MEM_TYPE_SHARED_MEMFD:
        pa_assert(memfd_fd != -1);
        fd = memfd_fd;
        break;
#endif
    default:
        goto fail;
    }

    if (fstat(fd, &st) < 0) {
        pa_log("fstat() failed: %s", pa_cstrerror(errno));
        goto fail;
    }

    if (st.st_size <= 0 ||
        st.st_size > (off_t) MAX_SHM_SIZE + (off_t) shm_marker_size(type) ||
        PA_ALIGN((size_t) st.st_size) != (size_t) st.st_size) {
        pa_log("Invalid shared memory segment size");
        goto fail;
    }

    prot = writable ? PROT_READ | PROT_WRITE : PROT_READ;
    if ((m->ptr = mmap(NULL, PA_PAGE_ALIGN(st.st_size), prot, MAP_SHARED, fd, (off_t) 0)) == MAP_FAILED) {
        pa_log("mmap() failed: %s", pa_cstrerror(errno));
        goto fail;
    }

    /* In case of attaching to memfd areas, _the caller_ maintains
     * ownership of the passed fd and has the sole responsibility
     * of closing it down.. For other types, we're the code path
     * which created the fd in the first place and we're thus the
     * ones responsible for closing it down */
    if (type != PA_MEM_TYPE_SHARED_MEMFD)
        pa_assert_se(pa_close(fd) == 0);

    m->type = type;
    m->id = id;
    m->size = (size_t) st.st_size;
    m->do_unlink = false;
    m->fd = -1;

    return 0;

fail:
    /* In case of memfds, caller maintains fd ownership */
    if (fd >= 0 && type != PA_MEM_TYPE_SHARED_MEMFD)
        pa_close(fd);

#endif /* defined(HAVE_SHM_OPEN) || defined(HAVE_MEMFD) */

    return -1;
}
Exemple #14
0
static int sharedmem_create(pa_shm *m, pa_mem_type_t type, size_t size, mode_t mode) {
#if defined(HAVE_SHM_OPEN) || defined(HAVE_MEMFD)
    char fn[32];
    int fd = -1;
    struct shm_marker *marker;
    bool do_unlink = false;

    /* Each time we create a new SHM area, let's first drop all stale
     * ones */
    pa_shm_cleanup();

    pa_random(&m->id, sizeof(m->id));

    switch (type) {
#ifdef HAVE_SHM_OPEN
    case PA_MEM_TYPE_SHARED_POSIX:
        segment_name(fn, sizeof(fn), m->id);
        fd = shm_open(fn, O_RDWR|O_CREAT|O_EXCL, mode);
        do_unlink = true;
        break;
#endif
#ifdef HAVE_MEMFD
    case PA_MEM_TYPE_SHARED_MEMFD:
        fd = memfd_create("pulseaudio", MFD_ALLOW_SEALING);
        break;
#endif
    default:
        goto fail;
    }

    if (fd < 0) {
        pa_log("%s open() failed: %s", pa_mem_type_to_string(type), pa_cstrerror(errno));
        goto fail;
    }

    m->type = type;
    m->size = size + shm_marker_size(type);
    m->do_unlink = do_unlink;

    if (ftruncate(fd, (off_t) m->size) < 0) {
        pa_log("ftruncate() failed: %s", pa_cstrerror(errno));
        goto fail;
    }

#ifndef MAP_NORESERVE
#define MAP_NORESERVE 0
#endif

    if ((m->ptr = mmap(NULL, PA_PAGE_ALIGN(m->size), PROT_READ|PROT_WRITE, MAP_SHARED|MAP_NORESERVE, fd, (off_t) 0)) == MAP_FAILED) {
        pa_log("mmap() failed: %s", pa_cstrerror(errno));
        goto fail;
    }

    if (type == PA_MEM_TYPE_SHARED_POSIX) {
        /* We store our PID at the end of the shm block, so that we
         * can check for dead shm segments later */
        marker = (struct shm_marker*) ((uint8_t*) m->ptr + m->size - shm_marker_size(type));
        pa_atomic_store(&marker->pid, (int) getpid());
        pa_atomic_store(&marker->marker, SHM_MARKER);
    }

    /* For memfds, we keep the fd open until we pass it
     * to the other PA endpoint over unix domain socket. */
    if (type == PA_MEM_TYPE_SHARED_MEMFD)
        m->fd = fd;
    else {
        pa_assert_se(pa_close(fd) == 0);
        m->fd = -1;
    }

    return 0;

fail:
    if (fd >= 0) {
#ifdef HAVE_SHM_OPEN
        if (type == PA_MEM_TYPE_SHARED_POSIX)
            shm_unlink(fn);
#endif
        pa_close(fd);
    }
#endif /* defined(HAVE_SHM_OPEN) || defined(HAVE_MEMFD) */

    return -1;
}