OpenCores
URL https://opencores.org/ocsvn/or1k/or1k/trunk

Subversion Repositories or1k

[/] [or1k/] [trunk/] [gdb-5.3/] [gdb/] [linux-proc.c] - Blame information for rev 1765

Details | Compare with Previous | View Log

Line No. Rev Author Line
1 1181 sfurman
/* GNU/Linux specific methods for using the /proc file system.
2
 
3
   Copyright 2001, 2002 Free Software Foundation, Inc.
4
 
5
   This file is part of GDB.
6
 
7
   This program is free software; you can redistribute it and/or modify
8
   it under the terms of the GNU General Public License as published by
9
   the Free Software Foundation; either version 2 of the License, or
10
   (at your option) any later version.
11
 
12
   This program is distributed in the hope that it will be useful,
13
   but WITHOUT ANY WARRANTY; without even the implied warranty of
14
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15
   GNU General Public License for more details.
16
 
17
   You should have received a copy of the GNU General Public License
18
   along with this program; if not, write to the Free Software
19
   Foundation, Inc., 59 Temple Place - Suite 330,
20
   Boston, MA 02111-1307, USA.  */
21
 
22
#include "defs.h"
23
#include "inferior.h"
24
#include <sys/param.h>  /* for MAXPATHLEN */
25
#include <sys/procfs.h> /* for elf_gregset etc. */
26
#include <sys/stat.h>   /* for struct stat */
27
#include <ctype.h>      /* for isdigit */
28
#include <unistd.h>     /* for open, pread64 */
29
#include <fcntl.h>      /* for O_RDONLY */
30
#include "regcache.h"   /* for registers_changed */
31
#include "gregset.h"    /* for gregset */
32
#include "gdbcore.h"    /* for get_exec_file */
33
#include "gdbthread.h"  /* for struct thread_info etc. */
34
#include "elf-bfd.h"    /* for elfcore_write_* */
35
#include "cli/cli-decode.h"     /* for add_info */
36
#include "gdb_string.h"
37
 
38
#ifndef O_LARGEFILE
39
#define O_LARGEFILE 0
40
#endif
41
 
42
/* Function: child_pid_to_exec_file
43
 *
44
 * Accepts an integer pid
45
 * Returns a string representing a file that can be opened
46
 * to get the symbols for the child process.
47
 */
48
 
49
char *
50
child_pid_to_exec_file (int pid)
51
{
52
  char *name1, *name2;
53
 
54
  name1 = xmalloc (MAXPATHLEN);
55
  name2 = xmalloc (MAXPATHLEN);
56
  make_cleanup (xfree, name1);
57
  make_cleanup (xfree, name2);
58
  memset (name2, 0, MAXPATHLEN);
59
 
60
  sprintf (name1, "/proc/%d/exe", pid);
61
  if (readlink (name1, name2, MAXPATHLEN) > 0)
62
    return name2;
63
  else
64
    return name1;
65
}
66
 
67
/* Function: read_mappings
68
 *
69
 * Service function for corefiles and info proc.
70
 */
71
 
72
static int
73
read_mapping (FILE *mapfile,
74
              long long *addr,
75
              long long *endaddr,
76
              char *permissions,
77
              long long *offset,
78
              char *device,
79
              long long *inode,
80
              char *filename)
81
{
82
  int ret = fscanf (mapfile,  "%llx-%llx %s %llx %s %llx",
83
                    addr, endaddr, permissions, offset, device, inode);
84
 
85
  if (ret > 0 && ret != EOF && *inode != 0)
86
    {
87
      /* Eat everything up to EOL for the filename.  This will prevent
88
       weird filenames (such as one with embedded whitespace) from
89
       confusing this code.  It also makes this code more robust
90
       in respect to annotations the kernel may add after the
91
       filename.
92
 
93
       Note the filename is used for informational purposes only.  */
94
      ret += fscanf (mapfile, "%[^\n]\n", filename);
95
    }
96
  else
97
    {
98
      filename[0] = '\0';        /* no filename */
99
      fscanf (mapfile, "\n");
100
    }
101
  return (ret != 0 && ret != EOF);
102
}
103
 
104
/* Function: linux_find_memory_regions
105
 *
106
 * Fills the "to_find_memory_regions" target vector.
107
 * Lists the memory regions in the inferior for a corefile.
108
 */
109
 
110
static int
111
linux_find_memory_regions (int (*func) (CORE_ADDR,
112
                                        unsigned long,
113
                                        int, int, int,
114
                                        void *),
115
                           void *obfd)
116
{
117
  long long pid = PIDGET (inferior_ptid);
118
  char mapsfilename[MAXPATHLEN];
119
  FILE *mapsfile;
120
  long long addr, endaddr, size, offset, inode;
121
  char permissions[8], device[8], filename[MAXPATHLEN];
122
  int read, write, exec;
123
  int ret;
124
 
125
  /* Compose the filename for the /proc memory map, and open it. */
126
  sprintf (mapsfilename, "/proc/%lld/maps", pid);
127
  if ((mapsfile = fopen (mapsfilename, "r")) == NULL)
128
    error ("Could not open %s\n", mapsfilename);
129
 
130
  if (info_verbose)
131
    fprintf_filtered (gdb_stdout,
132
                      "Reading memory regions from %s\n", mapsfilename);
133
 
134
  /* Now iterate until end-of-file. */
135
  while (read_mapping (mapsfile, &addr, &endaddr, &permissions[0],
136
                       &offset, &device[0], &inode, &filename[0]))
137
    {
138
      size = endaddr - addr;
139
 
140
      /* Get the segment's permissions.  */
141
      read  = (strchr (permissions, 'r') != 0);
142
      write = (strchr (permissions, 'w') != 0);
143
      exec  = (strchr (permissions, 'x') != 0);
144
 
145
      if (info_verbose)
146
        {
147
          fprintf_filtered (gdb_stdout,
148
                            "Save segment, %lld bytes at 0x%s (%c%c%c)",
149
                            size, paddr_nz (addr),
150
                            read  ? 'r' : ' ',
151
                            write ? 'w' : ' ',
152
                            exec  ? 'x' : ' ');
153
          if (filename && filename[0])
154
            fprintf_filtered (gdb_stdout,
155
                              " for %s", filename);
156
          fprintf_filtered (gdb_stdout, "\n");
157
        }
158
 
159
      /* Invoke the callback function to create the corefile segment. */
160
      func (addr, size, read, write, exec, obfd);
161
    }
162
  fclose (mapsfile);
163
  return 0;
164
}
165
 
166
/* Function: linux_do_thread_registers
167
 *
168
 * Records the thread's register state for the corefile note section.
169
 */
170
 
171
static char *
172
linux_do_thread_registers (bfd *obfd, ptid_t ptid,
173
                           char *note_data, int *note_size)
174
{
175
  gdb_gregset_t gregs;
176
  gdb_fpregset_t fpregs;
177
#ifdef FILL_FPXREGSET
178
  gdb_fpxregset_t fpxregs;
179
#endif
180
  unsigned long merged_pid = ptid_get_tid (ptid) << 16 | ptid_get_pid (ptid);
181
 
182
  fill_gregset (&gregs, -1);
183
  note_data = (char *) elfcore_write_prstatus (obfd,
184
                                               note_data,
185
                                               note_size,
186
                                               merged_pid,
187
                                               stop_signal,
188
                                               &gregs);
189
 
190
  fill_fpregset (&fpregs, -1);
191
  note_data = (char *) elfcore_write_prfpreg (obfd,
192
                                              note_data,
193
                                              note_size,
194
                                              &fpregs,
195
                                              sizeof (fpregs));
196
#ifdef FILL_FPXREGSET
197
  fill_fpxregset (&fpxregs, -1);
198
  note_data = (char *) elfcore_write_prxfpreg (obfd,
199
                                               note_data,
200
                                               note_size,
201
                                               &fpxregs,
202
                                               sizeof (fpxregs));
203
#endif
204
  return note_data;
205
}
206
 
207
struct linux_corefile_thread_data
208
{
209
  bfd *obfd;
210
  char *note_data;
211
  int *note_size;
212
  int num_notes;
213
};
214
 
215
/* Function: linux_corefile_thread_callback
216
 *
217
 * Called by gdbthread.c once per thread.
218
 * Records the thread's register state for the corefile note section.
219
 */
220
 
221
static int
222
linux_corefile_thread_callback (struct thread_info *ti, void *data)
223
{
224
  struct linux_corefile_thread_data *args = data;
225
  ptid_t saved_ptid = inferior_ptid;
226
 
227
  inferior_ptid = ti->ptid;
228
  registers_changed ();
229
  target_fetch_registers (-1);  /* FIXME should not be necessary;
230
                                   fill_gregset should do it automatically. */
231
  args->note_data = linux_do_thread_registers (args->obfd,
232
                                               ti->ptid,
233
                                               args->note_data,
234
                                               args->note_size);
235
  args->num_notes++;
236
  inferior_ptid = saved_ptid;
237
  registers_changed ();
238
  target_fetch_registers (-1);  /* FIXME should not be necessary;
239
                                   fill_gregset should do it automatically. */
240
  return 0;
241
}
242
 
243
/* Function: linux_make_note_section
244
 *
245
 * Fills the "to_make_corefile_note" target vector.
246
 * Builds the note section for a corefile, and returns it
247
 * in a malloc buffer.
248
 */
249
 
250
static char *
251
linux_make_note_section (bfd *obfd, int *note_size)
252
{
253
  struct linux_corefile_thread_data thread_args;
254
  struct cleanup *old_chain;
255
  char fname[16] = {'\0'};
256
  char psargs[80] = {'\0'};
257
  char *note_data = NULL;
258
  ptid_t current_ptid = inferior_ptid;
259
 
260
  if (get_exec_file (0))
261
    {
262
      strncpy (fname, strrchr (get_exec_file (0), '/') + 1, sizeof (fname));
263
      strncpy (psargs, get_exec_file (0),
264
               sizeof (psargs));
265
      if (get_inferior_args ())
266
        {
267
          strncat (psargs, " ",
268
                   sizeof (psargs) - strlen (psargs));
269
          strncat (psargs, get_inferior_args (),
270
                   sizeof (psargs) - strlen (psargs));
271
        }
272
      note_data = (char *) elfcore_write_prpsinfo (obfd,
273
                                                   note_data,
274
                                                   note_size,
275
                                                   fname,
276
                                                   psargs);
277
    }
278
 
279
  /* Dump information for threads.  */
280
  thread_args.obfd = obfd;
281
  thread_args.note_data = note_data;
282
  thread_args.note_size = note_size;
283
  thread_args.num_notes = 0;
284
  iterate_over_threads (linux_corefile_thread_callback, &thread_args);
285
  if (thread_args.num_notes == 0)
286
    {
287
      /* iterate_over_threads didn't come up with any threads;
288
         just use inferior_ptid.  */
289
      note_data = linux_do_thread_registers (obfd, inferior_ptid,
290
                                             note_data, note_size);
291
    }
292
  else
293
    {
294
      note_data = thread_args.note_data;
295
    }
296
 
297
  make_cleanup (xfree, note_data);
298
  return note_data;
299
}
300
 
301
/*
302
 * Function: linux_info_proc_cmd
303
 *
304
 * Implement the "info proc" command.
305
 */
306
 
307
static void
308
linux_info_proc_cmd (char *args, int from_tty)
309
{
310
  long long pid = PIDGET (inferior_ptid);
311
  FILE *procfile;
312
  char **argv = NULL;
313
  char buffer[MAXPATHLEN];
314
  char fname1[MAXPATHLEN], fname2[MAXPATHLEN];
315
  int cmdline_f = 1;
316
  int cwd_f = 1;
317
  int exe_f = 1;
318
  int mappings_f = 0;
319
  int environ_f = 0;
320
  int status_f = 0;
321
  int stat_f = 0;
322
  int all = 0;
323
  struct stat dummy;
324
 
325
  if (args)
326
    {
327
      /* Break up 'args' into an argv array. */
328
      if ((argv = buildargv (args)) == NULL)
329
        nomem (0);
330
      else
331
        make_cleanup_freeargv (argv);
332
    }
333
  while (argv != NULL && *argv != NULL)
334
    {
335
      if (isdigit (argv[0][0]))
336
        {
337
          pid = strtoul (argv[0], NULL, 10);
338
        }
339
      else if (strncmp (argv[0], "mappings", strlen (argv[0])) == 0)
340
        {
341
          mappings_f = 1;
342
        }
343
      else if (strcmp (argv[0], "status") == 0)
344
        {
345
          status_f = 1;
346
        }
347
      else if (strcmp (argv[0], "stat") == 0)
348
        {
349
          stat_f = 1;
350
        }
351
      else if (strcmp (argv[0], "cmd") == 0)
352
        {
353
          cmdline_f = 1;
354
        }
355
      else if (strncmp (argv[0], "exe", strlen (argv[0])) == 0)
356
        {
357
          exe_f = 1;
358
        }
359
      else if (strcmp (argv[0], "cwd") == 0)
360
        {
361
          cwd_f = 1;
362
        }
363
      else if (strncmp (argv[0], "all", strlen (argv[0])) == 0)
364
        {
365
          all = 1;
366
        }
367
      else
368
        {
369
          /* [...] (future options here) */
370
        }
371
      argv++;
372
    }
373
  if (pid == 0)
374
    error ("No current process: you must name one.");
375
 
376
  sprintf (fname1, "/proc/%lld", pid);
377
  if (stat (fname1, &dummy) != 0)
378
    error ("No /proc directory: '%s'", fname1);
379
 
380
  printf_filtered ("process %lld\n", pid);
381
  if (cmdline_f || all)
382
    {
383
      sprintf (fname1, "/proc/%lld/cmdline", pid);
384
      if ((procfile = fopen (fname1, "r")) > 0)
385
        {
386
          fgets (buffer, sizeof (buffer), procfile);
387
          printf_filtered ("cmdline = '%s'\n", buffer);
388
          fclose (procfile);
389
        }
390
      else
391
        warning ("unable to open /proc file '%s'", fname1);
392
    }
393
  if (cwd_f || all)
394
    {
395
      sprintf (fname1, "/proc/%lld/cwd", pid);
396
      memset (fname2, 0, sizeof (fname2));
397
      if (readlink (fname1, fname2, sizeof (fname2)) > 0)
398
        printf_filtered ("cwd = '%s'\n", fname2);
399
      else
400
        warning ("unable to read link '%s'", fname1);
401
    }
402
  if (exe_f || all)
403
    {
404
      sprintf (fname1, "/proc/%lld/exe", pid);
405
      memset (fname2, 0, sizeof (fname2));
406
      if (readlink (fname1, fname2, sizeof (fname2)) > 0)
407
        printf_filtered ("exe = '%s'\n", fname2);
408
      else
409
        warning ("unable to read link '%s'", fname1);
410
    }
411
  if (mappings_f || all)
412
    {
413
      sprintf (fname1, "/proc/%lld/maps", pid);
414
      if ((procfile = fopen (fname1, "r")) > 0)
415
        {
416
          long long addr, endaddr, size, offset, inode;
417
          char permissions[8], device[8], filename[MAXPATHLEN];
418
          char *header_fmt_string, *data_fmt_string;
419
 
420
          if (TARGET_ADDR_BIT == 32)
421
            {
422
              header_fmt_string = "\t%10s %10s %10s %10s %7s\n";
423
              data_fmt_string   = "\t%#10lx %#10lx %#10x %#10x %7s\n";
424
            }
425
          else
426
            {
427
              header_fmt_string = "  %18s %18s %10s %10s %7s\n";
428
              data_fmt_string   = "  %#18lx %#18lx %#10x %#10x %7s\n";
429
            }
430
 
431
          printf_filtered ("Mapped address spaces:\n\n");
432
          printf_filtered (header_fmt_string,
433
                           "Start Addr",
434
                           "  End Addr",
435
                           "      Size",
436
                           "    Offset",
437
                           "objfile");
438
 
439
          while (read_mapping (procfile, &addr, &endaddr, &permissions[0],
440
                               &offset, &device[0], &inode, &filename[0]))
441
            {
442
              size = endaddr - addr;
443
              printf_filtered (data_fmt_string,
444
                               (unsigned long) addr, /* FIXME: pr_addr */
445
                               (unsigned long) endaddr,
446
                               (int) size,
447
                               (unsigned int) offset,
448
                               filename[0] ? filename : "");
449
 
450
            }
451
 
452
          fclose (procfile);
453
        }
454
      else
455
        warning ("unable to open /proc file '%s'", fname1);
456
    }
457
  if (status_f || all)
458
    {
459
      sprintf (fname1, "/proc/%lld/status", pid);
460
      if ((procfile = fopen (fname1, "r")) > 0)
461
        {
462
          while (fgets (buffer, sizeof (buffer), procfile) != NULL)
463
            printf_filtered (buffer);
464
          fclose (procfile);
465
        }
466
      else
467
        warning ("unable to open /proc file '%s'", fname1);
468
    }
469
  if (stat_f || all)
470
    {
471
      sprintf (fname1, "/proc/%lld/stat", pid);
472
      if ((procfile = fopen (fname1, "r")) > 0)
473
        {
474
          int itmp;
475
          char ctmp;
476
 
477
          if (fscanf (procfile, "%d ", &itmp) > 0)
478
            printf_filtered ("Process: %d\n", itmp);
479
          if (fscanf (procfile, "%s ", &buffer[0]) > 0)
480
            printf_filtered ("Exec file: %s\n", buffer);
481
          if (fscanf (procfile, "%c ", &ctmp) > 0)
482
            printf_filtered ("State: %c\n", ctmp);
483
          if (fscanf (procfile, "%d ", &itmp) > 0)
484
            printf_filtered ("Parent process: %d\n", itmp);
485
          if (fscanf (procfile, "%d ", &itmp) > 0)
486
            printf_filtered ("Process group: %d\n", itmp);
487
          if (fscanf (procfile, "%d ", &itmp) > 0)
488
            printf_filtered ("Session id: %d\n", itmp);
489
          if (fscanf (procfile, "%d ", &itmp) > 0)
490
            printf_filtered ("TTY: %d\n", itmp);
491
          if (fscanf (procfile, "%d ", &itmp) > 0)
492
            printf_filtered ("TTY owner process group: %d\n", itmp);
493
          if (fscanf (procfile, "%u ", &itmp) > 0)
494
            printf_filtered ("Flags: 0x%x\n", itmp);
495
          if (fscanf (procfile, "%u ", &itmp) > 0)
496
            printf_filtered ("Minor faults (no memory page): %u\n",
497
                             (unsigned int) itmp);
498
          if (fscanf (procfile, "%u ", &itmp) > 0)
499
            printf_filtered ("Minor faults, children: %u\n",
500
                             (unsigned int) itmp);
501
          if (fscanf (procfile, "%u ", &itmp) > 0)
502
            printf_filtered ("Major faults (memory page faults): %u\n",
503
                             (unsigned int) itmp);
504
          if (fscanf (procfile, "%u ", &itmp) > 0)
505
            printf_filtered ("Major faults, children: %u\n",
506
                             (unsigned int) itmp);
507
          if (fscanf (procfile, "%d ", &itmp) > 0)
508
            printf_filtered ("utime: %d\n", itmp);
509
          if (fscanf (procfile, "%d ", &itmp) > 0)
510
            printf_filtered ("stime: %d\n", itmp);
511
          if (fscanf (procfile, "%d ", &itmp) > 0)
512
            printf_filtered ("utime, children: %d\n", itmp);
513
          if (fscanf (procfile, "%d ", &itmp) > 0)
514
            printf_filtered ("stime, children: %d\n", itmp);
515
          if (fscanf (procfile, "%d ", &itmp) > 0)
516
            printf_filtered ("jiffies remaining in current time slice: %d\n",
517
                             itmp);
518
          if (fscanf (procfile, "%d ", &itmp) > 0)
519
            printf_filtered ("'nice' value: %d\n", itmp);
520
          if (fscanf (procfile, "%u ", &itmp) > 0)
521
            printf_filtered ("jiffies until next timeout: %u\n",
522
                             (unsigned int) itmp);
523
          if (fscanf (procfile, "%u ", &itmp) > 0)
524
            printf_filtered ("jiffies until next SIGALRM: %u\n",
525
                             (unsigned int) itmp);
526
          if (fscanf (procfile, "%d ", &itmp) > 0)
527
            printf_filtered ("start time (jiffies since system boot): %d\n",
528
                             itmp);
529
          if (fscanf (procfile, "%u ", &itmp) > 0)
530
            printf_filtered ("Virtual memory size: %u\n",
531
                             (unsigned int) itmp);
532
          if (fscanf (procfile, "%u ", &itmp) > 0)
533
            printf_filtered ("Resident set size: %u\n",
534
                             (unsigned int) itmp);
535
          if (fscanf (procfile, "%u ", &itmp) > 0)
536
            printf_filtered ("rlim: %u\n",
537
                             (unsigned int) itmp);
538
          if (fscanf (procfile, "%u ", &itmp) > 0)
539
            printf_filtered ("Start of text: 0x%x\n", itmp);
540
          if (fscanf (procfile, "%u ", &itmp) > 0)
541
            printf_filtered ("End of text: 0x%x\n", itmp);
542
          if (fscanf (procfile, "%u ", &itmp) > 0)
543
            printf_filtered ("Start of stack: 0x%x\n", itmp);
544
#if 0   /* Don't know how architecture-dependent the rest is... 
545
           Anyway the signal bitmap info is available from "status".  */
546
          if (fscanf (procfile, "%u ", &itmp) > 0)       /* FIXME arch? */
547
            printf_filtered ("Kernel stack pointer: 0x%x\n", itmp);
548
          if (fscanf (procfile, "%u ", &itmp) > 0)       /* FIXME arch? */
549
            printf_filtered ("Kernel instr pointer: 0x%x\n", itmp);
550
          if (fscanf (procfile, "%d ", &itmp) > 0)
551
            printf_filtered ("Pending signals bitmap: 0x%x\n", itmp);
552
          if (fscanf (procfile, "%d ", &itmp) > 0)
553
            printf_filtered ("Blocked signals bitmap: 0x%x\n", itmp);
554
          if (fscanf (procfile, "%d ", &itmp) > 0)
555
            printf_filtered ("Ignored signals bitmap: 0x%x\n", itmp);
556
          if (fscanf (procfile, "%d ", &itmp) > 0)
557
            printf_filtered ("Catched signals bitmap: 0x%x\n", itmp);
558
          if (fscanf (procfile, "%u ", &itmp) > 0)       /* FIXME arch? */
559
            printf_filtered ("wchan (system call): 0x%x\n", itmp);
560
#endif
561
          fclose (procfile);
562
        }
563
      else
564
        warning ("unable to open /proc file '%s'", fname1);
565
    }
566
}
567
 
568
void
569
_initialize_linux_proc (void)
570
{
571
  extern void inftarg_set_find_memory_regions ();
572
  extern void inftarg_set_make_corefile_notes ();
573
 
574
  inftarg_set_find_memory_regions (linux_find_memory_regions);
575
  inftarg_set_make_corefile_notes (linux_make_note_section);
576
 
577
  add_info ("proc", linux_info_proc_cmd,
578
            "Show /proc process information about any running process.\n\
579
Specify any process id, or use the program being debugged by default.\n\
580
Specify any of the following keywords for detailed info:\n\
581
  mappings -- list of mapped memory regions.\n\
582
  stat     -- list a bunch of random process info.\n\
583
  status   -- list a different bunch of random process info.\n\
584
  all      -- list all available /proc info.");
585
}
586
 
587
int linux_proc_xfer_memory (CORE_ADDR addr, char *myaddr, int len, int write,
588
                            struct mem_attrib *attrib,
589
                            struct target_ops *target)
590
{
591
  int fd, ret;
592
  char filename[64];
593
 
594
  if (write)
595
    return 0;
596
 
597
  /* Don't bother for one word.  */
598
  if (len < 3 * sizeof (long))
599
    return 0;
600
 
601
  /* We could keep this file open and cache it - possibly one
602
     per thread.  That requires some juggling, but is even faster.  */
603
  sprintf (filename, "/proc/%d/mem", PIDGET (inferior_ptid));
604
  fd = open (filename, O_RDONLY | O_LARGEFILE);
605
  if (fd == -1)
606
    return 0;
607
 
608
  /* If pread64 is available, use it.  It's faster if the kernel
609
     supports it (only one syscall), and it's 64-bit safe even
610
     on 32-bit platforms (for instance, SPARC debugging a SPARC64
611
     application).
612
 
613
     We play some autoconf and CFLAGS games to get this declaration
614
     exposed: -D_XOPEN_SOURCE=500 -D_LARGEFILE64_SOURCE.  And then
615
     a -D_BSD_SOURCE to counteract the defaults for _XOPEN_SOURCE.  */
616
#ifdef HAVE_PREAD64
617
  if (pread64 (fd, myaddr, len, addr) != len)
618
#else
619
  if (lseek (fd, addr, SEEK_SET) == -1
620
      || read (fd, myaddr, len) != len)
621
#endif
622
    ret = 0;
623
  else
624
    ret = len;
625
 
626
  close (fd);
627
  return ret;
628
}

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.