{"id":19604136,"url":"https://github.com/zedthree/fortran-gdb-pp","last_synced_at":"2026-05-14T17:37:00.914Z","repository":{"id":145381105,"uuid":"111221450","full_name":"ZedThree/Fortran-gdb-pp","owner":"ZedThree","description":"Pretty printer for Fortran dynamic types in gdb","archived":false,"fork":false,"pushed_at":"2017-11-18T18:13:31.000Z","size":19,"stargazers_count":4,"open_issues_count":3,"forks_count":0,"subscribers_count":4,"default_branch":"master","last_synced_at":"2025-01-18T00:54:02.160Z","etag":null,"topics":["fortran","gdb","pretty-print"],"latest_commit_sha":null,"homepage":null,"language":"Python","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"gpl-3.0","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/ZedThree.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null}},"created_at":"2017-11-18T16:39:02.000Z","updated_at":"2020-03-27T05:16:55.000Z","dependencies_parsed_at":"2023-06-03T16:30:41.314Z","dependency_job_id":null,"html_url":"https://github.com/ZedThree/Fortran-gdb-pp","commit_stats":{"total_commits":14,"total_committers":1,"mean_commits":14.0,"dds":0.0,"last_synced_commit":"81e06304e43734772683274f7ba9052bb17f9992"},"previous_names":[],"tags_count":0,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ZedThree%2FFortran-gdb-pp","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ZedThree%2FFortran-gdb-pp/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ZedThree%2FFortran-gdb-pp/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ZedThree%2FFortran-gdb-pp/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/ZedThree","download_url":"https://codeload.github.com/ZedThree/Fortran-gdb-pp/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":240887289,"owners_count":19873533,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["fortran","gdb","pretty-print"],"created_at":"2024-11-11T09:34:58.701Z","updated_at":"2026-05-14T17:37:00.877Z","avatar_url":"https://github.com/ZedThree.png","language":"Python","funding_links":[],"categories":[],"sub_categories":[],"readme":"Fortran-gdb-pp\n==============\n\nA gdb pretty printer for Fortran dynamic types\n\nThis is currently only \"proof of concept\", and is by no means\nguaranteed to work. It works for *me* with `gfortran 7.2` and `gdb\n8.0.1`, and the very small number of programs I've tried.\n\nHow to use\n----------\n\nStart gdb, then:\n\n```\npython exec(open(\"fortran_printer.py\").read())\n```\n\nWhat's the problem?\n-------------------\n\nPolymorphic objects don't get printed nicely in gdb. Take the program\n[gdb_mvce.f90](./gdb_mvce.f90) with a breakpoint on line 46. Printing\n`alloc_ext` gives:\n\n```\n(gdb) p alloc_ext1\n$1 = ( _data = 0x606260, _vptr = 0x400da0\n     \u003c__foo_module_MOD___vtab_foo_module_My_extended_type\u003e )\n```\n\nwhich is not very helpful. In order to see the actual value of\n`alloc_ext`, we need to do\n\n```\n(gdb) p *(my_extended_type*)(alloc_ext1%_data)\n$2 = ( my_base_type = ( base_char = 'base' ), extended_char = 'ext ' )\n```\n\nbecause gdb thinks `alloc_ext1%_data` is a pointer to a `my_base_type`\nand not a `my_extended_type`. This quickly becomes frustrating if your\ntype has polymorphic components.\n\nWith Fortran-gdb-pp, we instead get:\n\n```\n(gdb) p alloc_ext1\n$3 = ( my_base_type = ( base_char = 'base' ), extended_char = 'ext ' )\n```\n\nHow does it work?\n-----------------\n\nUnfortunately, we have to work around several limitations of the gdb\npython API. Firstly, gdb reports the `dynamic_type` of a polymorphic\nvariable as being its base type, and not its actual dynamic type! This\nmeans we need some other way of getting its dynamic type. Luckily, the\nsymbol for the `_vptr` component (at least with gfortran 7.2) contains\nthe dynamic type, so we can use this. Briefly, we do the following:\n\n1. Look up symbol for the value's `_vptr`\n2. Parse the symbol to get the dynamic type\n3. Cast the `_data` component to a pointer to the dynamic type and\n   dereference\n\nFor 1., we need to get the `_vptr` symbol. We can do this\nin gdb with `info symbol foo%_vptr`. The python API lacks such a\nfunction, so instead we do:\n\n```\ngdb.execute(\"info symbol {:#x}\".format(int(val['_vptr'])))\n```\n\n`int(val['_vptr'])` gets the address of `_vptr`\n\nNext, we need to parse the symbol. With gfortran 7.2, `_vptr` symbols\nlook like either:\n\n- `__\u003cmodule name\u003e_MOD___vtab_\u003cmodule name\u003e_\u003cDynamic type\u003e` for types\n  defined in modules, or\n- `__vab_\u003cprogram name\u003e_\u003cDynamic type\u003e.nnnn` for types defined in\n  programs\n\nModule and program names can contain underscores, but luckily the type\nstarts with a capital letter while everything else is in lower case.\n\nLastly, we need to actually print the `_data` component as the dynamic\ntype. While the python API does provide a `Value.cast(type)` method,\nthe `type` argument must be a `gdb.Type` object. No matter, we can use\nthe `gdb.lookup_type(name)` function... except that this doesn't work\nwith Fortran types. This time, we fallback to using\n`gdb.parse_and_eval`:\n\n```\ncast_string = \"*({type}*)({address:#x})\".format(\n    type=real_type, address=int(val['_data']))\nreal_val = gdb.parse_and_eval(cast_string)\n```\n\nwhere `real_type` is a string containing the dynamic type. This\nbasically executes `*(\u003cdynamic type\u003e)(value%_data)` and then we can\npass the resulting value to a pretty printer that just returns\n`str(val)`, i.e. like the default printer.\n\n\nKnown issues\n------------\n\n- printing allocatable variables before they've been allocated will\n  crash gdb\n- accessing components of dynamic types is still annoying, as you\n  still need to go through the intermediate `_data` component, which\n  gdb thinks is a pointer to a base type object\n\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fzedthree%2Ffortran-gdb-pp","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fzedthree%2Ffortran-gdb-pp","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fzedthree%2Ffortran-gdb-pp/lists"}