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

Subversion Repositories riscv_vhdl

[/] [riscv_vhdl/] [trunk/] [debugger/] [src/] [libdbg64g/] [api_utils.cpp] - Blame information for rev 4

Details | Compare with Previous | View Log

Line No. Rev Author Line
1 4 sergeykhbr
/*
2
 *  Copyright 2018 Sergey Khabarov, sergeykhbr@gmail.com
3
 *
4
 *  Licensed under the Apache License, Version 2.0 (the "License");
5
 *  you may not use this file except in compliance with the License.
6
 *  You may obtain a copy of the License at
7
 *
8
 *      http://www.apache.org/licenses/LICENSE-2.0
9
 *
10
 *  Unless required by applicable law or agreed to in writing, software
11
 *  distributed under the License is distributed on an "AS IS" BASIS,
12
 *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13
 *  See the License for the specific language governing permissions and
14
 *  limitations under the License.
15
 */
16
 
17
#include <string.h>
18
#include <stdlib.h>
19
#include <time.h>
20
#include <iostream>
21
#include <dirent.h>
22
#if defined(_WIN32) || defined(__CYGWIN__)
23
#else
24
    #include <dlfcn.h>
25
#endif
26
#include "api_types.h"
27
#include "api_utils.h"
28
#include "attribute.h"
29
#include "iservice.h"
30
#include "iclass.h"
31
#include "coreservices/irawlistener.h"
32
 
33
namespace debugger {
34
 
35
/** Plugin Entry point type definition */
36
typedef void (*plugin_init_proc)();
37
 
38
/** Temporary buffer for the log messages. */
39
static char bufLog[1024*1024];
40
static int uniqueIdx_ = 0;
41
 
42
/** Redirect output to specified console. */
43
static AttributeType default_console(Attr_List);
44
mutex_def mutexDefaultConsoles_;
45
 
46
/** */
47
static FILE *logfile_ = 0;
48
 
49
static AttributeType log_file(Attr_String);
50
 
51
/** Mutex to avoid concurency for the output stream among threads. */
52
mutex_def mutex_printf;
53
 
54
/** Core log message interface object. */
55
extern IFace *getInterface(const char *name);
56
 
57
extern "C" void RISCV_generate_name(AttributeType *name) {
58
    char str[256];
59
    RISCV_sprintf(str, sizeof(str), "obj_%08x", uniqueIdx_++);
60
    name->make_string(str);
61
}
62
 
63
extern "C" void RISCV_add_default_output(void *iout) {
64
    AttributeType lstn(static_cast<IRawListener *>(iout));
65
    RISCV_mutex_lock(&mutexDefaultConsoles_);
66
    default_console.add_to_list(&lstn);
67
    RISCV_mutex_unlock(&mutexDefaultConsoles_);
68
}
69
 
70
extern "C" void RISCV_remove_default_output(void *iout) {
71
    RISCV_mutex_lock(&mutexDefaultConsoles_);
72
    for (unsigned i = 0; i < default_console.size(); i++) {
73
        if (default_console[i].to_iface() == iout) {
74
            default_console.remove_from_list(i);
75
            break;
76
        }
77
    }
78
    RISCV_mutex_unlock(&mutexDefaultConsoles_);
79
}
80
 
81
extern "C" int RISCV_enable_log(const char *filename) {
82
    if (logfile_) {
83
        fclose(logfile_);
84
        logfile_ = NULL;
85
    }
86
    logfile_ = fopen(filename, "w");
87
    if (!logfile_) {
88
        return 1;
89
    }
90
    return 0;
91
}
92
 
93
extern "C" void RISCV_disable_log() {
94
    if (logfile_) {
95
        fclose(logfile_);
96
    }
97
    logfile_ = 0;
98
}
99
 
100
extern "C" void RISCV_print_bin(int level, char *buf, int len) {
101
    std::cout.write(buf, len);
102
    //osLog.write(buf,len);
103
    //osLog.flush();
104
 
105
}
106
 
107
extern "C" int RISCV_printf(void *iface, int level,
108
                            const char *fmt, ...) {
109
    int ret = 0;
110
    va_list arg;
111
    IFace *iout = reinterpret_cast<IFace *>(iface);
112
 
113
    RISCV_mutex_lock(&mutex_printf);
114
    if (iout == NULL) {
115
        ret = RISCV_sprintf(bufLog, sizeof(bufLog), "[%s]: ", "unknown");
116
    } else if (strcmp(iout->getFaceName(), IFACE_SERVICE) == 0) {
117
        IService *iserv = static_cast<IService *>(iout);
118
        AttributeType *local_level =
119
                static_cast<AttributeType *>(iserv->getAttribute("LogLevel"));
120
        if (level > static_cast<int>(local_level->to_int64())) {
121
            RISCV_mutex_unlock(&mutex_printf);
122
            return 0;
123
        }
124
        ret = RISCV_sprintf(bufLog, sizeof(bufLog), "[%s]: ",
125
                                                   iserv->getObjName());
126
    } else if (strcmp(iout->getFaceName(), IFACE_CLASS) == 0) {
127
        IClass *icls = static_cast<IClass *>(iout);
128
        ret = RISCV_sprintf(bufLog, sizeof(bufLog), "[%s]: ",
129
                                                   icls->getClassName());
130
    } else {
131
        ret = RISCV_sprintf(bufLog, sizeof(bufLog), "[%s]: ",
132
                                                   iout->getFaceName());
133
    }
134
    va_start(arg, fmt);
135
#if defined(_WIN32) || defined(__CYGWIN__)
136
    ret += vsprintf_s(&bufLog[ret], sizeof(bufLog) - ret, fmt, arg);
137
#else
138
    ret += vsprintf(&bufLog[ret], fmt, arg);
139
#endif
140
    va_end(arg);
141
 
142
    bufLog[ret++] = '\n';
143
    bufLog[ret] = '\0';
144
    IRawListener *ilstn;
145
    RISCV_mutex_lock(&mutexDefaultConsoles_);
146
    for (unsigned i = 0; i < default_console.size(); i++) {
147
        ilstn = static_cast<IRawListener *>(default_console[i].to_iface());
148
        ilstn->updateData(bufLog, ret);
149
    }
150
    RISCV_mutex_unlock(&mutexDefaultConsoles_);
151
    if (logfile_) {
152
        fwrite(bufLog, ret, 1, logfile_);
153
        fflush(logfile_);
154
    }
155
    RISCV_mutex_unlock(&mutex_printf);
156
    return ret;
157
}
158
 
159
extern "C" int RISCV_sprintf(char *s, size_t len, const char *fmt, ...) {
160
    int ret;
161
    va_list arg;
162
    va_start(arg, fmt);
163
#if defined(_WIN32) || defined(__CYGWIN__)
164
    ret = vsprintf_s(s, len, fmt, arg);
165
#else
166
    ret = vsprintf(s, fmt, arg);
167
#endif
168
    va_end(arg);
169
    return ret;
170
}
171
 
172
/* Suspend thread on certain number of milliseconds */
173
extern "C" void RISCV_sleep_ms(int ms) {
174
#if defined(_WIN32) || defined(__CYGWIN__)
175
    Sleep(ms);
176
#else
177
    usleep(1000*ms);
178
#endif
179
}
180
 
181
extern "C" uint64_t RISCV_get_time_ms() {
182
#if defined(_WIN32) || defined(__CYGWIN__)
183
    return 1000*(clock()/CLOCKS_PER_SEC);
184
#else
185
    struct timeval tc;
186
    gettimeofday(&tc, NULL);
187
    return 1000*tc.tv_sec + tc.tv_usec/1000;
188
#endif
189
}
190
 
191
extern "C" int RISCV_get_pid() {
192
#if defined(_WIN32) || defined(__CYGWIN__)
193
    return _getpid();
194
#else
195
    return getpid();
196
#endif
197
}
198
 
199
extern "C" void RISCV_memory_barrier() {
200
#if defined(_WIN32) || defined(__CYGWIN__)
201
    MemoryBarrier();
202
#else
203
    __sync_synchronize();
204
#endif
205
}
206
 
207
extern "C" void RISCV_thread_create(void *data) {
208
    LibThreadType *p = (LibThreadType *)data;
209
#if defined(_WIN32) || defined(__CYGWIN__)
210
    p->Handle = (thread_def)_beginthreadex(0, 0, p->func, p->args, 0, 0);
211
#else
212
    pthread_create(&p->Handle, 0, p->func, p->args);
213
#endif
214
}
215
 
216
extern "C" uint64_t RISCV_thread_id() {
217
          uint64_t r;
218
#if defined(_WIN32) || defined(__CYGWIN__)
219
          r = GetCurrentThreadId();
220
#else
221
          r = pthread_self();
222
#endif
223
          return r;
224
}
225
 
226
extern "C" void RISCV_thread_join(thread_def th, int ms) {
227
#if defined(_WIN32) || defined(__CYGWIN__)
228
    WaitForSingleObject(th, ms);
229
#else
230
    pthread_join(th, 0);
231
#endif
232
}
233
 
234
extern "C" void RISCV_event_create(event_def *ev, const char *name) {
235
#if defined(_WIN32) || defined(__CYGWIN__)
236
    ev->state = false;
237
    ev->cond = CreateEvent(
238
                NULL,               // default security attributes
239
                TRUE,               // manual-reset event
240
                FALSE,              // initial state is nonsignaled
241
                TEXT(name)          // object name
242
                );
243
#else
244
    pthread_mutex_init(&ev->mut, NULL);
245
    pthread_cond_init(&ev->cond, NULL);
246
    ev->state = false;
247
#endif
248
}
249
 
250
extern "C" void RISCV_event_close(event_def *ev) {
251
#if defined(_WIN32) || defined(__CYGWIN__)
252
    CloseHandle(ev->cond);
253
#else
254
    pthread_mutex_destroy(&ev->mut);
255
    pthread_cond_destroy(&ev->cond);
256
#endif
257
}
258
 
259
extern "C" void RISCV_event_set(event_def *ev) {
260
#if defined(_WIN32) || defined(__CYGWIN__)
261
    ev->state = true;
262
    SetEvent(ev->cond);
263
#else
264
    pthread_mutex_lock(&ev->mut);
265
    ev->state = true;
266
    pthread_mutex_unlock(&ev->mut);
267
    pthread_cond_signal(&ev->cond);
268
#endif
269
}
270
 
271
extern "C" int RISCV_event_is_set(event_def *ev) {
272
    return ev->state ? 1: 0;
273
}
274
 
275
extern "C" void RISCV_event_clear(event_def *ev) {
276
#if defined(_WIN32) || defined(__CYGWIN__)
277
    ev->state = false;
278
    ResetEvent(ev->cond);
279
#else
280
    ev->state = false;
281
#endif
282
}
283
 
284
extern "C" void RISCV_event_wait(event_def *ev) {
285
#if defined(_WIN32) || defined(__CYGWIN__)
286
    WaitForSingleObject(ev->cond, INFINITE);
287
#else
288
    int result = 0;
289
    pthread_mutex_lock(&ev->mut);
290
    while (result == 0 && !ev->state) {
291
        result = pthread_cond_wait(&ev->cond, &ev->mut);
292
    }
293
    pthread_mutex_unlock(&ev->mut);
294
#endif
295
}
296
 
297
extern "C" int RISCV_event_wait_ms(event_def *ev, int ms) {
298
#if defined(_WIN32) || defined(__CYGWIN__)
299
    DWORD wait_ms = ms;
300
    if (ms == 0) {
301
        wait_ms = INFINITE;
302
    }
303
    if (WAIT_TIMEOUT == WaitForSingleObject(ev->cond, wait_ms)) {
304
        return 1;
305
    }
306
    return 0;
307
#else
308
    struct timeval tc;
309
    struct timespec ts;
310
    int next_us;
311
    int result = 0;
312
    gettimeofday(&tc, NULL);
313
    next_us = tc.tv_usec + 1000 * ms;
314
    ts.tv_sec = tc.tv_sec + (next_us / 1000000);
315
    next_us -= 1000000 * (next_us / 1000000);
316
    ts.tv_nsec = 1000 * next_us;
317
 
318
    pthread_mutex_lock(&ev->mut);
319
    while (result == 0 && !ev->state) {
320
        result = pthread_cond_timedwait(&ev->cond, &ev->mut, &ts);
321
    }
322
    pthread_mutex_unlock(&ev->mut);
323
    if (ETIMEDOUT == result) {
324
        return 1;
325
    }
326
    return 0;
327
#endif
328
}
329
 
330
extern "C" sharemem_def RISCV_memshare_create(const char *name, int sz) {
331
    sharemem_def ret = 0;
332
#if defined(_WIN32) || defined(__CYGWIN__)
333
    ret = CreateFileMapping(
334
                 INVALID_HANDLE_VALUE,  // use paging file
335
                 NULL,                  // default security
336
                 PAGE_READWRITE,      // read/write access
337
                 0,                   // maximum object size (high-order DWORD)
338
                 sz,                  // maximum object size (low-order DWORD)
339
                 name);               // name of mapping object
340
#else
341
#endif
342
    if (!ret) {
343
        RISCV_error("Couldn't create map object %s", name);
344
    }
345
    return ret;
346
}
347
 
348
extern "C" void* RISCV_memshare_map(sharemem_def h, int sz) {
349
    void *ret = 0;
350
#if defined(_WIN32) || defined(__CYGWIN__)
351
    ret = MapViewOfFile(h,   // handle to map object
352
                        FILE_MAP_ALL_ACCESS, // read/write permission
353
                        0,
354
                        0,
355
                        sz);
356
#else
357
#endif
358
    if (!ret) {
359
        RISCV_error("Couldn't map view of file with size %d", sz);
360
    }
361
    return ret;
362
}
363
 
364
extern "C" void RISCV_memshare_unmap(void *buf) {
365
#if defined(_WIN32) || defined(__CYGWIN__)
366
    UnmapViewOfFile(buf);
367
#else
368
#endif
369
}
370
 
371
extern "C" void RISCV_memshare_delete(sharemem_def h) {
372
#if defined(_WIN32) || defined(__CYGWIN__)
373
    CloseHandle(h);
374
#else
375
#endif
376
}
377
 
378
extern "C" int RISCV_mutex_init(mutex_def *mutex) {
379
#if defined(_WIN32) || defined(__CYGWIN__)
380
    InitializeCriticalSection(mutex);
381
#else
382
    pthread_mutex_init(mutex, NULL);
383
#endif
384
    return 0;
385
}
386
 
387
extern "C" int RISCV_mutex_lock(mutex_def *mutex) {
388
#if defined(_WIN32) || defined(__CYGWIN__)
389
    EnterCriticalSection(mutex);
390
#else
391
    pthread_mutex_lock(mutex) ;
392
#endif
393
    return 0;
394
}
395
 
396
extern "C" int RISCV_mutex_unlock(mutex_def * mutex) {
397
#if defined(_WIN32) || defined(__CYGWIN__)
398
    LeaveCriticalSection(mutex);
399
#else
400
    pthread_mutex_unlock(mutex);
401
#endif
402
    return 0;
403
}
404
 
405
extern "C" int RISCV_mutex_destroy(mutex_def *mutex) {
406
#if defined(_WIN32) || defined(__CYGWIN__)
407
    DeleteCriticalSection(mutex);
408
#else
409
    pthread_mutex_destroy(mutex);
410
#endif
411
    return 0;
412
}
413
 
414
extern "C" void *RISCV_malloc(uint64_t sz) {
415
    return malloc((size_t)sz);
416
}
417
 
418
extern "C" void RISCV_free(void *p) {
419
    if (p) {
420
        free(p);
421
    }
422
}
423
 
424
extern "C" int RISCV_get_core_folder(char *out, int sz) {
425
#if defined(_WIN32) || defined(__CYGWIN__)
426
    HMODULE hm = NULL;
427
    if (!GetModuleHandleExA(GET_MODULE_HANDLE_EX_FLAG_FROM_ADDRESS |
428
            GET_MODULE_HANDLE_EX_FLAG_UNCHANGED_REFCOUNT,
429
            (LPCSTR)&RISCV_get_core_folder,
430
            &hm)) {
431
 
432
        return GetLastError();
433
    }
434
    GetModuleFileNameA(hm, out, sz);
435
#else
436
    Dl_info dl_info;
437
    dladdr((void *)RISCV_get_core_folder, &dl_info);
438
    RISCV_sprintf(out, sz, "%s", dl_info.dli_fname);
439
#endif
440
    int n = (int)strlen(out);
441
    while (n > 0 && out[n] != '\\' && out[n] != '/') n--;
442
 
443
    out[n+1] = '\0';
444
    return 0;
445
}
446
 
447
extern "C" void RISCV_set_current_dir() {
448
#if defined(_WIN32) || defined(__CYGWIN__)
449
    HMODULE hMod = GetModuleHandle(NULL);
450
    char path[MAX_PATH] = "";
451
    GetModuleFileNameA(hMod, path, MAX_PATH);
452
#else         // Linux
453
    // Get path of executable.
454
    char path[1024];
455
    ssize_t n = readlink("/proc/self/exe", path, sizeof(path)/sizeof(path[0]) - 1);
456
    if (n == -1) {
457
        return;
458
    }
459
    path[n] = 0;
460
#endif
461
 
462
    size_t i;
463
    for(i = strlen(path) - 1; i > 0 && path[i] != '/' && path[i] != '\\'; --i);
464
    path[i] = '\0';
465
 
466
#if defined(_WIN32) || defined(__CYGWIN__)
467
    SetCurrentDirectoryA(path);
468
#else         // Linux
469
    chdir(path);
470
#endif
471
}
472
 
473
/**
474
 * @brief   Loading all plugins from the 'plugins' sub-folder.
475
 * @details I suppose only one folders level so no itteration algorithm.
476
 */
477
void _load_plugins(AttributeType *list) {
478
#if defined(_WIN32) || defined(__CYGWIN__)
479
    HMODULE hlib;
480
#else
481
    void *hlib;
482
#endif
483
    DIR *dir;
484
    struct dirent *ent;
485
    plugin_init_proc plugin_init;
486
    char curdir[1024];
487
    std::string plugin_dir, plugin_lib;
488
 
489
    RISCV_get_core_folder(curdir, sizeof(curdir));
490
 
491
    plugin_dir = std::string(curdir) + "plugins/";
492
    dir = opendir(plugin_dir.c_str());
493
 
494
    if (dir == NULL) {
495
          RISCV_error("Plugins directory '%s' not found", curdir);
496
          return;
497
    }
498
 
499
    while ((ent = readdir(dir)) != NULL) {
500
        if (ent->d_type != DT_REG) {
501
            continue;
502
        }
503
        if ((strstr(ent->d_name, ".dll") == NULL)
504
         && (strstr(ent->d_name, ".so") == NULL)) {
505
            continue;
506
        }
507
        plugin_lib = plugin_dir + std::string(ent->d_name);
508
#if defined(_WIN32) || defined(__CYGWIN__)
509
        if ((hlib = LoadLibrary(plugin_lib.c_str())) == 0) {
510
            continue;
511
        }
512
        plugin_init = (plugin_init_proc)GetProcAddress(hlib, "plugin_init");
513
        if (!plugin_init) {
514
            FreeLibrary(hlib);
515
            continue;
516
        }
517
#else
518
        // reset errors
519
        dlerror();
520
        if ((hlib = dlopen(plugin_lib.c_str(), RTLD_LAZY)) == 0) {
521
            printf("Can't open library '%s': %s\n",
522
                       plugin_lib.c_str(), dlerror());
523
            continue;
524
        }
525
        plugin_init = (plugin_init_proc)dlsym(hlib, "plugin_init");
526
        if (dlerror()) {
527
            printf("Not found plugin_init() in file '%s'\n",
528
                       plugin_lib.c_str());
529
            dlclose(hlib);
530
            continue;
531
        }
532
#endif
533
 
534
        RISCV_info("Loading plugin file '%s'", plugin_lib.c_str());
535
        plugin_init();
536
 
537
        AttributeType item;
538
        item.make_list(2);
539
        item[0u] = AttributeType(plugin_lib.c_str());
540
        item[1] = AttributeType(Attr_UInteger,
541
                                reinterpret_cast<uint64_t>(hlib));
542
        list->add_to_list(&item);
543
    }
544
    closedir(dir);
545
}
546
 
547
void _unload_plugins(AttributeType *list) {
548
    const char *plugin_name;
549
    for (unsigned i = 0; i < list->size(); i++) {
550
        if (!(*list)[i].is_list()) {
551
            RISCV_error("Can't free plugin[%d] library", i);
552
            continue;
553
        }
554
        plugin_name = (*list)[i][0u].to_string();
555
#if defined(_WIN32) || defined(__CYGWIN__)
556
        HMODULE hlib = reinterpret_cast<HMODULE>((*list)[i][1].to_uint64());
557
        FreeLibrary(hlib);
558
#else
559
        void *hlib = reinterpret_cast<void *>((*list)[i][1].to_uint64());
560
        if (strstr(plugin_name, "gui_plugin") == 0) {
561
            /** It's a workaround to avoid SIGSEGV on application exiting.
562
             *  It's a specific of dynamically linked QT-libraries. They
563
             *  create and use global variable freeing on application
564
             *  closing.
565
             */
566
            dlclose(hlib);
567
        }
568
#endif
569
    }
570
}
571
 
572
void put_char(char s, FILE *f) {
573
    fputc(s, f);
574
    fflush(f);
575
}
576
 
577
// check if this attribute like list with items <= 2: [a,b]
578
bool is_single_line(const char *s) {
579
    bool ret = false;
580
    if (*s == '[') {
581
        const char *pcheck = s + 1;
582
        int item_cnt = 0;
583
        int symbol_cnt = 0;
584
        while (*pcheck != ']') {
585
            symbol_cnt++;
586
            if (*pcheck == ',') {
587
                item_cnt++;
588
            } else if (*pcheck == '[' || *pcheck == '{') {
589
                item_cnt = 100;
590
                break;
591
            }
592
            ++pcheck;
593
        }
594
        if (item_cnt <= 2 && symbol_cnt < 80) {
595
            ret = true;
596
        }
597
    }
598
    return ret;
599
}
600
 
601
const char *writeAttrToFile(FILE *f, const char *s, int depth) {
602
    const char *ret = s;
603
    bool end_attr = false;
604
    bool do_single_line = false;
605
 
606
    if ((*s) == 0) {
607
        return ret;
608
    }
609
 
610
    put_char('\n', f);
611
    for (int i = 0; i < depth; i++) {
612
        put_char(' ', f);
613
        put_char(' ', f);
614
    }
615
 
616
 
617
    while ((*ret) && !end_attr) {
618
        put_char(*ret, f);
619
        if ((*ret) == ',') {
620
            if (!do_single_line) {
621
                put_char('\n', f);
622
                for (int i = 0; i < depth; i++) {
623
                    put_char(' ', f);
624
                    put_char(' ', f);
625
                }
626
            }
627
        } else if ((*ret) == ']' || (*ret) == '}') {
628
            if (do_single_line) {
629
                do_single_line = false;
630
            } else {
631
                return ret;
632
            }
633
        } else if ((*ret) == '[' || (*ret) == '{') {
634
            do_single_line = is_single_line(ret);
635
            if (!do_single_line) {
636
                ret = writeAttrToFile(f, ret + 1, depth + 1);
637
            }
638
        }
639
        ++ret;
640
    }
641
 
642
    return ret;
643
}
644
 
645
void RISCV_write_json_file(const char *filename, const char *s) {
646
    FILE *f = fopen(filename, "w");
647
    if (!f) {
648
        return;
649
    }
650
    writeAttrToFile(f, s, 0);
651
    fclose(f);
652
}
653
 
654
int RISCV_read_json_file(const char *filename, void *outattr) {
655
    AttributeType *out = reinterpret_cast<AttributeType *>(outattr);
656
    FILE *f = fopen(filename, "r");
657
    if (!f) {
658
        return 0;
659
    }
660
    fseek(f, 0, SEEK_END);
661
    int sz = ftell(f);
662
    out->make_data(sz);
663
 
664
    fseek(f, 0, SEEK_SET);
665
    fread(out->data(), sz, 1, f);
666
    return sz;
667
}
668
 
669
}  // namespace debugger

powered by: WebSVN 2.1.0

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